Кратко

  • Одинаковое значение IPv6-адреса ограниченной области может существовать в разных зонах. Узел добавляет отдельный локальный zone index, выбирает по нему интерфейс и не помещает индекс в пакет.
  • RFC 6874 в 2013 году попытался включить ZoneID в URI. RFC 9844 в 2025 году признал подход непрактичным для браузеров и заменил его требованием к UI: принять, проверить и локально преобразовать идентификатор, не делая его глобальной идентичностью.

Число, верное только здесь и сейчас

Программа сохранила, что обращение к fe80::1 прошло через интерфейс с индексом 7. Это точная запись состояния одного ядра в один момент. На другой машине индекс 7 может принадлежать иному адаптеру; после перестройки сетевого namespace даже на той же машине соответствие может измениться.

Ограничение заложено в адресной архитектуре. RFC 4291 определяет link-local адрес для одного канала и запрещает маршрутизатору пересылать на другой канал пакет с link-local источником или назначением. На двух независимых каналах допустим один и тот же fe80::1.

RFC 4007 в марте 2005 года разделил scope и zone. Scope — размер топологической области, zone — конкретный экземпляр области такого размера. Link-local — характеристика масштаба; конкретный подключённый канал — зона.

Сам адрес не сообщает, к какой зоне относится. Узел, включённый в несколько зон одного scope, назначает им собственные индексы. Они строго локальны и не обязаны совпадать даже у соседей на одном канале.

Поэтому сохранённый индекс — не имя удалённого ресурса. Это доказательство решения отправляющей стороны, смысл которого зависит от карты интерфейсов этой стороны.

Нормализация не продлевает срок жизни индекса

RFC 5952 в 2010 году сократил количество равнозначных текстовых представлений IPv6. Правила сжатия нулей, регистра и квадратных скобок при порте помогают сравнивать конфигурации и журналы.

Но стандарт не охватывает зонное расширение RFC 4007. RFC 9844 прямо отмечает этот предел. Канонический адрес остаётся совместимым, а %eth0 или %7 продолжает зависеть от хоста.

Не спасает и зона по умолчанию. RFC 4007 рекомендует defaults, обычно обозначая выбор нулём. RFC 9844 фиксирует, что не все ОС дают пригодную default zone, и называет Linux.

Если утилита выполнила операцию без явного значения, это доказывает лишь наличие локальной подстановки. В новом окружении она может исчезнуть. Для воспроизводимости нужны адрес, исходный идентификатор, полученный индекс, хост и время, а не одна «нормализованная строка».

Ввод без общей грамматики

RFC 4007 не установил единый набор символов и максимальную длину zone identifier. Смысл нечисловых строк остался за реализациями. Свобода поддерживает разные ОС, но переносит обязанность проверки в UI.

RFC 9844 рекомендует подходящий предел длины и отказ от опасных значений, включая NUL. Held erratum 8553 для RFC 4007 отмечает недостающие ограничения и направляет к новой рекомендации по безопасности.

Строка проходит через форму, shell, конфигурацию, URI-парсер, лог и системный вызов. Повторное декодирование, усечение или разная нормализация способны сделать показанный интерфейс не тем, чей индекс получил kernel.

Успешная операция через %eth0 доказывает только локальное соответствие и работу пути в данный момент. Она не аутентифицирует удалённый узел, не подтверждает владение адресом, не даёт глобальной достижимости и не переносит имя на другой хост.

Отдельное поле в сокетном интерфейсе

RFC 3493, опубликованный в феврале 2003 года, закрепил разделение в sockaddr_in6. В sin6_addr находятся 128 бит адреса, а в sin6_scope_id — отдельный 32-битный селектор.

Селектор передают локальному ядру вместе с адресом. Он не становится дополнительной частью IPv6-адреса и не появляется в поле пакета. Ядро использует его для локального выбора, после чего смысл числа исчерпан.

Тот же RFC определяет функции соответствия имени и индекса интерфейса. if_nametoindex() обращается к системе исполнения. Неизвестное имя означает ошибку, а не запрос к глобальному реестру. Никакого международного соглашения о значении eth0 нет.

RFC 4007 рекомендовал текстовую форму <address>%<zone_id>. Реализациям следует принимать неотрицательное десятичное значение, а также разрешено поддерживать локальные строки, например имена интерфейсов. Scope уже виден из адреса, поэтому суффиксу достаточно различать зоны данного scope.

Форма бессмысленна для глобальных адресов и не должна применяться к loopback. Она предназначена для одного узла и не передаётся по сети, если все интерпретаторы заранее не согласовали её семантику.

Так число или имя остаётся рядом с тем, кто способен его проверить. Получатель не видит чужую внутреннюю номенклатуру и не должен ей доверять.

Отмена расширения и новое требование

В августе 2025 года RFC 9844 полностью объявил RFC 6874 устаревшим: разработчики браузеров сочли подход непрактичным. Документ также отменил обновление RFC 3986; проверенный erratum 8552 закрепляет изменение.

Теперь обязанность лежит на интерфейсе пользователя. UI, принимающий адрес, отличный от global unicast, должен позволить ввести или выбрать zone identifier. Предпочтительна полная %-форма, но допустимы отдельное поле, список, иной разделитель или отдельный параметр.

Программа хранит адрес и идентификатор раздельно, преобразует второй в локальный индекс и должна сообщать ошибку для неверного значения. POSIX inet_pton() самостоятельно не разбирает fe80::1%eth0. Нужен getaddrinfo() либо разделение строки с inet_pton() и if_nametoindex().

RFC 9844 исключает семантику загрузки URI браузером. Он не создаёт переносимый HTTP origin и не обещает универсальную ссылку. Он стандартизует возможность выразить локальный выбор и удерживает его вне адреса и сети.

Это не отказ от функции. Это отказ приписывать функции большую область действия, чем она способна выдержать.

Локальный аргумент в глобальной грамматике

RFC 3986, январь 2005 года, описывает URI как идентификаторы глобального масштаба, хотя действие может учитывать контекст пользователя. Символ % начинает percent-encoding, а буквальный процент в данных записывается как %25.

RFC 6874 в 2013 году предложил для части HTTP URI в квадратных скобках форму [fe80::a%25en1]. %25 обозначал разделитель %, за которым следовал локальный ZoneID. Целью был доступ браузера или иной URI-программы к link-local устройству.

Документ одновременно признавал: ZoneID имеет смысл только на исходном узле и должен удаляться до включения в исходящий HTTP-запрос. Видимая часть URI переставала быть его частью перед передачей.

Возникали вопросы о сравнении origin, истории, закладках, прокси и порядке декодирования. Если две подсистемы раскрывали %25 на разных шагах, локальный выбор мог измениться вместе с синтаксисом.

Проблему нельзя было решить только новым разделителем. Аргумент одного хоста попал в форму, которую принято переносить, долго хранить и сравнивать между системами.

Контекст, который заканчивается до провода

Пользователь выражает намерение, UI проверяет строку, ОС преобразует имя, socket передаёт индекс, IP применяет границу scope. До выхода пакета zone identifier уже сделал всё необходимое.

Каждая стадия подтверждает отдельный факт. Принятый текст — ещё не существующий интерфейс. Успешное преобразование — ещё не активный канал. Отправка — ещё не подтверждённая идентичность ответившей стороны. Надёжный журнал не сворачивает эти выводы в одну отметку «адрес верен».

Адресу не хватало местного контекста для выполнения операции, но не для существования в IPv6. Не перенося контекст, архитектура избавилась от глобальной координации имён интерфейсов. Индекс полезен именно потому, что его власть прекращается на границе хоста.

Источники