Кратко
- RFC 3338 помещал транслятор между API сокетов и стеками IPv4/IPv6 хоста. Для узла только с AAAA он мог синтезировать ответ A из локального пула IPv4 и сопоставить значение настоящему IPv6-адресу, не переводя заголовки IP.
- Значение, которое видел процесс, было состоянием транслятора с областью действия и поколением. Исчерпание пула, вытеснение и повторное использование, различия семантики API и разрыв между AAAA хоста и поддержкой IPv6 конкретным сервисом разрушали эту иллюзию.
Резолвер возвращал форму, понятную старой программе
Приложение, рассчитанное только на IPv4, ожидало результаты типа gethostbyname и структуры сокетов IPv4. Переписать его могло быть невозможно: исходный код отсутствовал, а поставщик прекратил работу. RFC 3338 адресовал именно этот переходный промежуток, когда на хосте уже был нативный стек IPv6, но некоторые бинарные программы оставались привязаны к прежнему интерфейсу.
Резолвер BIA перехватывал вызов и искал записи A и AAAA. Если находился только AAAA, модуль отображения адресов выбирал значение из внутреннего пула IPv4, сохранял пару IPv4–IPv6 и создавал для программы ответ A. Приложение получало знакомую четырёхбайтовую форму и продолжало работу без изменений.
Позже программа передавала это значение функции сокета IPv4. Модуль отображения функций перехватывал вызов, находил IPv6-адрес и вызывал соответствующий интерфейс IPv6. Пакеты шли через нативный стек IPv6. В отличие от Bump-in-the-Stack из RFC 2767, BIA не требовал переписывать заголовки IPv4 и IPv6 на сетевом уровне.
Мнимый адрес указывал на строку таблицы
Обычный сетевой адрес предполагает устойчивое толкование: значение идентифицирует удалённый интерфейс или конечную точку. Синтетическое значение BIA означало гораздо меньше. Лишь в конкретной таблице транслятора, в заданной области и в одном поколении оно ссылалось на IPv6-адрес.
RFC 3338 приводил в пример не назначенные значения от 0.0.0.1 до 0.0.0.255 для внутреннего пула. Они не должны были покидать хост. Уникальность требовалась только внутри границ транслятора. Таблицы на узел, пользователя или процесс могли придавать одинаковым битам разные значения.
Поэтому журнал, сохранивший только синтетическое число, неоднозначен. Полезное доказательство включает область таблицы, поколение записи, причину создания, IPv6-референт, набор DNS-ответов и процесс-владелец. Такой «адрес» был ближе к файловому дескриптору, чем к глобально значимой цели.
После повторного использования вчерашний дескриптор вёл к другому узлу
Пул конечен. Если множество приложений IPv4 обращалось к множеству IPv6-хостов, значения могли закончиться. RFC рассматривал освобождение самого старого отображения и повторную выдачу его IPv4-значения. Ёмкость восстанавливалась, но объект ссылки менялся.
Старая копия в приложении, кэше, журнале или отложенном обратном вызове могла по-прежнему выглядеть действительной. Однако следующий поиск по таблице переводил её уже к другому IPv6-хосту. Конфликт глобальной маршрутизации не требовался: достаточно было разного понимания срока жизни внутри одной машины, чтобы получить ошибочную доставку и атрибуцию.
Надёжная цепочка должна фиксировать выделение, последнее использование, вытеснение, повторную выдачу и поколение. Вызов сокета следует связывать с поколением, действовавшим в тот момент. Одинаковые четыре байта до и после повторной выдачи — не одна и та же операционная идентичность.
Перевод функции не делал семантику двух API одинаковой
Модуль функций переводил вызовы сокетов IPv4 в соответствующие вызовы IPv6, но RFC 3338 предупреждал о неполной совместимости. В IPv6 были возможности без прямого аналога в IPv4. Сырые сокеты, вспомогательные данные, значения ICMP, правила подстановки и адреса внутри прикладных протоколов требовали решений, зависящих от операционной системы.
Успешная замена функции доказывала лишь факт вызова, но не сохранение смысла всех параметров, ошибок и побочных эффектов. Приложение могло зависеть от семейства адресов, размера структуры, формата результата или определённой ошибки, которую транслятор не воспроизводил точно.
Поэтому квитанция раздельно хранит имя и аргументы исходного API, имя и аргументы полученного API, преобразование параметров, реализацию ОС, возвращённое состояние и толкование приложением. Отсутствие перевода заголовков упрощало один слой, но не отменяло семантический перевод.
AAAA хоста не доказывал поддержку IPv6 на выбранном порту
Двухстековый сервер мог публиковать AAAA, потому что часть его служб поддерживала IPv6, а программа на нужном порту всё ещё слушала только IPv4. Клиент с BIA мог выбрать путь AAAA, достичь машины и всё же потерпеть неудачу на границе службы.
RFC 3338 обсуждал перебор всех возвращённых адресов. Для TCP механизм мог заметить неудачу connect и перейти к следующему варианту. В UDP успешная отправка не обязательно давала немедленный наблюдаемый ответ; транслятору было трудно или невозможно определить, какой адрес сработал, и перебор мог оставаться обязанностью приложения.
Это разделяет четыре разных факта. DNS доказывает, что у имени есть записи. Сетевая достижимость — что пакет приходит к адресу. Слушающий порт — что существует вход в сервис. Успех приложения — что требуемая операция выполнена. Ни одна квитанция не заменяет следующую.
Совместимость могла стать поводом не переносить программу
RFC провёл строгую границу применения. BIA имел статус Experimental и предназначался для ранних пользователей IPv6 со старыми приложениями, исходники которых недоступны. Для обычной эксплуатации он не рекомендовался. Если код существовал, программу следовало портировать, а BIA не должен был служить оправданием отсрочки.
Предупреждение описывало и институциональный риск. Мост, закрывающий сегодняшнюю брешь, накапливает отображения, исключения, мониторинг и операционные зависимости. Нынешний владелец сохраняет старую программу; будущие операторы наследуют скрытое поведение резолвера и зависящее от состояния значение адресов. Снять мост может оказаться сложнее, чем выполнить исходный перенос.
В акт внедрения нужны критерии выхода: какие программы действительно подходят под исключение, кто отвечает за перенос, какие вызовы не поддерживаются и какое наблюдение разрешит убрать слой. Слово «временно» без этих условий легко становится постоянной архитектурой.
Позднейшая гонка соединений решала соседнюю задачу иначе
BIS из RFC 2767 размещал перевод ниже в стеке и опирался на SIIT из RFC 2765. RFC 3338 намеренно перенёс адаптацию к границе API. RFC 2893 задавал тогдашний контекст двухстекового перехода, RFC 3493 позднее описал базовые расширения сокетов IPv6, а RFC 4038 разобрал варианты миграции приложений.
RFC 6555 и его обновление RFC 8305 позднее задали подходы Happy Eyeballs, которые упорядочивают или сталкивают попытки соединения в разных семействах адресов. Они уменьшают задержку и обеспечивают откат, не превращая синтетический IPv4 в частный псевдоним IPv6-узла. Приписывать эти алгоритмы BIA задним числом — значит стереть историческую разницу между выбором реальных кандидатов и созданием изменяемого локального дескриптора.
RFC 4291 определяет архитектуру адресации IPv6, но не придаёт глобального смысла внутреннему пулу IPv4 в BIA. Ни один из этих стандартов также не доказывает, что поставщик или оператор действительно внедрял RFC 3338. Описание механизма не равно свидетельству развёртывания.
Каждому дескриптору совместимости нужно поколение
Элегантность BIA состояла в сохранении интерфейса, видимого приложению, при замене реализации под ним. Ценой было скрытое состояние. То, что выглядело адресом, стало ссылкой в изменяемую таблицу; обычный на вид вызов сокета стал перехватываемым переводом.
Долговечное операционное правило — записывать представление вместе с системой, имеющей право его толковать. Синтетическому ответу A нужна квитанция отображения. Переведённому вызову — исходная и конечная семантика. Соединению — реальный IPv6-адрес и порт, результат транспорта и результат приложения.
Без этих связей расследователь видит IPv4-подобное число и приписывает ему глобальное значение, которого никогда не было. RFC 3338 был переходным механизмом и одновременно уроком о дескрипторах: биты не являются идентичностью; смысл им придаёт живое, проверяемое отображение.
Источники
- RFC 3338 — Dual Stack Hosts Using Bump-in-the-API
- Запись RFC Editor о RFC 3338
- RFC 2767 — Bump-in-the-Stack
- RFC 2765 — SIIT
- RFC 2893 — Transition Mechanisms for IPv6 Hosts and Routers
- RFC 3493 — Basic Socket Interface Extensions for IPv6
- RFC 4038 — Application Aspects of IPv6 Transition
- RFC 6555 — Happy Eyeballs
- RFC 8305 — Happy Eyeballs Version 2
- RFC 4291 — IPv6 Addressing Architecture
Обзор для участников
Подробный контекст профиля
Войдите с подходящим уровнем подписки, чтобы открыть полный обзор и примечания к источникам.
Только для Стратегического сообщества
Стратегическое сообщество
Открыто всем читателям. Вступите и войдите, чтобы открыть обзоры профилей.
Вступить в Стратегическое сообществоТолько для Альянса лидеров
Альянс лидеров
Для проверенных владельцев IP-активов и руководителей. Войдите, чтобы открыть обзоры Альянса.
Вступить в Альянс лидеров
