Преобразование IPv4/IPv6
Это авторский перевод статьи с сайта разработчиков Jool - модуля ядра linux, который занимается SIIT и NAT64. Один из примеров использования этого модуля можно найти в другой моей заметке про NAT64 и DNS64.
Введение
Основная проблема перехода на IPv6 заключается в том, что пакеты IPv4 и IPv6 несовместимы друг с другом. Узел, который работает только с IPv4, не может напрямую взаимодействовать с узлом, работающим только по IPv6.
Типичный пакет IPv4 состоит из заголовка IPv4, заголовка TCP (или UDP) и блока полезной нагрузки:
Типичный пакет IPv6 состоит из заголовка IPv6, заголовка TCP (или UDP) и блока полезной нагрузки:
Таким образом, задача транслятора IP состоит в том, чтобы заменить заголовки IP, оставив полезную нагрузку без изменений:
Большая часть заголовка легко преобразуется между протоколами. Единственная чувствительная часть — это IP-адреса. Стратегии трансляции адресов — это то, что отличает разные типы трансляции.
Большинство механизмов трансляции IP были разработаны Internet Engineering Task Force (IETF) и формально определены в нескольких различных документах RFC.
Существует три различных основных типа трансляторов IP:
- SIIT, также известный как «Stateless NAT64», или NAT без отслеживания состояния;
- Stateful NAT64 - NAT с отслеживанием состояния (NAT-шесть-четыре, а не NAT-«шестьдесят четыре»);
- MAP-T.
Эти типы, наряду с другими стратегиями преобразования адресов, будут объяснены в следующих разделах.
SIIT (EAMT)
Наиболее простой метод. Рассмотрим следующую схему.
(T означает «транслятор»)
Предполагая, что шлюзом по умолчанию для всех является «T», узлы «A» (IPv6) и «V» (IPv4) будут связываться следующим образом:
- вы говорите «T» (согласно конфигурации SIIT-EAM): «Замени 2001:db8:6::8 на 203.0.113.8, а 192.0.2.16 на 2001:db8:4::16»;
- вы сообщаете «A» (например, через DNS): «адрес «V» — 2001:db8:4::16».
- вы сообщаете «V» (например, через DNS): «адрес «А» — 203.0.113.8».
Что произойдет:
Транслятор «обманывает» каждый узел, заставляя его думать, что другой может использовать его протокол. Это стратегия преобразования адресов, при которой вы назначаете определенные адреса определенным узлам.
Применение:
Транслятор SIIT (EAM) можно использовать, когда есть ограниченное количество узлов IPv6, требующих взаимодействия с ограниченным числом узлов IPv4. Независимо от того, назначено ли это явно или неявно, каждому участвующему узлу для работы потребуется как выделенный адрес IPv4, так и выделенный адрес IPv6.
SIIT — это устройство (или служба) сетевого уровня, которое просто меняет адреса IPv4 и IPv6 в соответствии с таблицей преобразования статических адресов.
С другой стороны, «Таблица явного сопоставления адресов» (EAMT, англ. Explicit Address Mapping Table) — это конкретный, используемый здесь, механизм преобразования адресов. Это таблица, в которой каждая строка сопоставляет произвольные адреса IPv4 с соответствующими адресами IPv6 и наоборот.
Вот пример EAMT, который позволит обмениваться данными между всеми узлами в сети, изображенной выше:
IPv6 | IPv4 |
---|---|
2001:db8:6::8 | 203.0.113.8 |
2001:db8:6::9 | 203.0.113.9 |
2001:db8:6::a | 203.0.113.10 |
2001:db8:6::b | 203.0.113.11 |
2001:db8:6::c | 203.0.113.12 |
2001:db8:4::16 | 192.0.2.16 |
2001:db8:4::17 | 192.0.2.17 |
2001:db8:4::18 | 192.0.2.18 |
2001:db8:4::19 | 192.0.2.19 |
2001:db8:4::20 | 192.0.2.20 |
Учитывая приведенную выше конфигурацию, узлы IPv6 воспринимают сеть следующим образом:
Со стороны узлов IPv4 это выглядит так:
Схема EAMT здесь упрощена для наглядной иллюстрации. По правде говоря, это более универсально, чем просто позволять привязывать одиночные произвольные адреса к другим одиночным произвольным адресам. Дополнительную информацию можно найти в официальной спецификации RFC 7757.
SIIT (traditional)
На самом деле это изначально разработанная форма SIIT - традиционный SIIT. Дли иллюстрации рассмотрим сеть с IPv6:
Идея состоит в том, чтобы просто удалить префикс при переводе с IPv6 на IPv4 и добавить его в другом направлении:
Как видите, этот механизм преобразования позволяет преобразовать любой IPv4-адрес в IPv6-адрес с помощью одного простого настраиваемого префикса IPv6. Обратное преобразование, однако, не всегда возможно. Для перевода IPv6-адресу требуется действительный общедоступный IPv4-адрес (в дополнение к префиксу), что не всегда доступно.
Применение:
Вы можете использовать традиционный SIIT, когда у вас есть ограниченное количество узлов IPv6, желающих взаимодействовать с любым количеством узлов IPv4. Как и в случае с EAM SIIT, каждому участнику потребуются (явные или неявные) адреса IPv4 и IPv6.
Вы можете заметить, что IPv4-адреса имеют длину 32 бита, что точно соответствует длине суффикса префикса перевода (128 - 96). Другими словами, буквально весь Интернет IPv4 свободно умещается в хвосте 2001:db8::.
Имейте в виду, что традиционный SIIT накладывает ограничения на ваши IPv6-адреса, что может оказаться нецелесообразным.
Когда SIIT изначально задумывался, то, что мы называем «традиционным» режимом, было единственным ожидаемым алгоритмом преобразования адресов без сохранения состояния. По этой причине, можно предположить, ему не дали официального названия. При быстром поиске спецификации IETF, как правило, ссылаются на него с помощью таких терминов, как «stateless address mapping algorithm defined in[RFC6052]», «IPv4-Embedded IPv6 Address Format» или «[RFC6052] algorithm». Далее будет использоваться неофициальное «традиционное» прозвище для обозначения алгоритма и «pool6» для обозначения префикса.
Как выглядит сеть сто стороны узлов IPv6 и IPv4:
Вы можете найти формальное определение традиционного алгоритма преобразования адресов в RFC 6052.
SIIT-DC
SIIT-DC (SIIT для центров обработки данных c IPv6) — это скорее архитектура, чем выделенный механизм преобразования адресов, но я включаю его здесь, потому что (а) это полезный и гораздо более приземленный сценарий трансляции без сохранения состояния и (б) это прекрасная возможность показать, как EAMT и pool6 работают вместе.
Может сложиться впечатление, что SIIT «EAMT» и «традиционный» SIIT относятся к разным типам трансляторов. Это не так: это всё SIIT. Ожидается, что современная реализация всегда будет сначала пытаться преобразовать адрес на основе EAMT, а если сопоставление не будет найдено, вернуться к добавлению или удалению pool6. Разделение было сделано выше только в иллюстративных целях.
Предположим, у вас есть ЦОД только для IPv6. Чтобы сэкономить место, мы покажем, что у него всего два сервера. Сервер s6a должен быть доступен только удаленным клиентам IPv6. При этом s6b также должен быть доступен и клинтам с IPv4:
Примечание! Пограничный ретранслятор (BR) — это просто шлюз, который в контексте SIIT-DC является просто транслятором SIIT.
По сути, префикс pool6 используется только для маскировки интернет-узлов IPv4 (это шаблон, который вы будете часто видеть в дальнейшем, потому что он хорошо работает), тогда как EAMT используется для маскировки серверов IPv6.
Предположим, что BR имеет следующую конфигурацию:
Можно также добавить по одной записи EAM для каждого сервера датацентра, который должен быть доступен по IPv4.
Вот ожидаемый поток пакетов между вашим сервером EAM и случайным интернет-клиентом IPv4:
Применение:
Таким образом, любой Интернет-узел IPv4 может получить доступ к вашим серверам EAM, и только ваши серверы EAM могут отвечать. Вы также не обязаны назначать ограниченные IPv6-адреса своим серверам, эффективно получая преимущества как традиционного, так и EAM, но не недостатки ни того, ни другого. Также стоит упомянуть, что большая часть вашего центра обработки данных отличается простотой использования только IPv6, поскольку IPv4 был переведен в разряд «услуг».
Префикс «64:ff9b:1::/48» официально зарезервирован и общеизвестен как «Префикс трансляции IPv4/IPv6 для локального использования». Вы можете свободно использовать его для перевода в своей сети, если вы не маршрутизируете его глобально. Если вам интересно, это определено в RFC 8215.
Обратите внимание, что транслятор никоим образом не влияет на обычный трафик IPv6:
Естественное, с точки зрения DNS запись A для «s6b» должна быть 203.0.113.6, а запись AAAA — 2001:db8:12:34:1. Как обычно, вы фактически предоставили «s6b» двойной стек (то есть возможности как IPv4, так и IPv6) без его ведома.
Вот как «s6b» видит сеть:
Вот как «s6a» и «c6» видят сеть:
А так видит «c4»:
SIIT-DC формально определен в RFC 7755.
SIIT-DC: Dual Translation Mode
Несмотря на то, что ваш центр обработки данных работает только с IPv6, пользователи по прежнему могут иметь необходимость использовать IPv4.
Вы не сможете обеспечить их потребности с помощью IPv6, но если вы все еще хотите иметь в основном центре обработки данных IPv6, вы можете изолировать таких клиентов на небольших островах с IPv4, при этом сохранить большую часть своей инфраструктуры на IPv6. Этот метод известен как «SIIT-DC: режим двойной трансляции» (SIIT-DC-2XLAT).
Применение:
Это просто резюме предыдущих двух абзацев. Вы должны использовать SIIT-DC-2xlat, когда вам нужен SIIT-DC, но вам также нужны острова IPv4 в качестве обходного пути для устаревшего программного обеспечения.
В контексте SIIT-DC-2xlat, транслятор, который обслуживает определенный остров, называется Edge Relay (ER). Это обычный SIIT.
Остальная часть сети — обычный SIIT-DC. Узлы «c6», «s6a» и «s6b» видят сеть также, как в SIIT-DC. Отличия только у «c4»
и у «s4»
SIIT-DC-2xlat формально описан в RFC 7756.
NAPT
Преобразование сетевых адресов и портов (NAPT) (обычно известное как «NAT» или, точнее, «Stateful NAT») не является механизмом преобразования IPv6/IPv4, но может помочь понять Stateful NAT64 из-за их сходства. Поэтому этот раздел является напоминанием о том, как работает NAPT.
NAPT — это хак, цель которого минимизировать количество глобальных («белых») IPv4-адресов используемых вашей «частной сетью». Почему? Потому что в мире официально закончились адреса IPv4. По сути, левой сети были назначены «фальшивые» адреса 192.168 (т. е. «частные» адреса IPv4), а работа NAPT заключается в замене адресов источников пакетов с целью открытия доступа частных узлов ко внешней сети. Это обманывает узлы во внешней сети, заставляя их думать, что трафик, запущенный частными узлами на самом деле был отправлен от узла с NAPT:
«A» хочет запросить HTTP-ресурс у «V». Поэтому он отправляет пакет на 203.0.113.16:80. Адрес источника — это его собственный IP, а порт источника был выбран случайным образом при привязке сокета. Это нормально и не зависит от NAPT.
Когда первый пакет «A» поступает в NAPT, последний понимает, что ему не хватает сопоставления для 192.168.0.8:1234, поэтому он открывает новый сокет (1) в сторону «V». Опять же, исходный адрес — это его собственный IP-адрес, а исходный порт также выбирается случайным образом.
С этого момента он будет действовать как посредник и копировать данные, полученные из одного сокета, в другой (2).
Поскольку нет никакой алгоритмической связи между частным адресом и соответствующим маскирующим публичным адресом (т. е. любой публичный адрес может использоваться для маскировки любого частного сокета), NAPT ведет динамическую таблицу (3), которая запоминает сопоставления (где «сопоставление» определяется как ссылка на два сокета). В данном случае он хранит связь между 192.168.0.8:1234 и 203.0.113.1:5678:
Затем сопоставление используется для сопоставления двух сокетов для каждого последующего пакета в соединении, что обеспечивает согласованность адресации:
Таким образом, фактически предоставили доступ в интернет всем частным узлам IPv4 за счет одного общедоступного IPv4-адреса, вместо предоставления каждому из них отдельного IPv4-адреса.
Применение:
Вам нужен NAPT, когда вам нужно уменьшить количество используемых вами IPv4-адресов, и вам не нужен IPv6.
Опять же, NAPT не является механизмом трансляции IPv4/IPv6. В Linux используйте стандартные iptables/nftables для запуска NAPT. В контексте iptables/nftables это называется «Masquerade».
Сопоставления создаются по мере необходимости и уничтожаются по истечении определенного времени бездействия. Именно из-за этой динамической таблицы мы называем NAPT — «Stateful NAT».
Для внешних узлов можно сказать, что узлы от «A» до «E» «совместно используют» глобальный адрес (или адреса) NAPT. Вы можете думать о NAPT как о не вредоносном устройстве «человек посередине», которое выдает себя за всех участников, мультиплексируя частные сокеты со своими публичными:
Например, 192.168.0.8:1234 думает, что общается напрямую с 203.0.113.16:80, но на самом деле NAPT незаметно преобразовывает трафик. Поскольку NAPT открыл свой собственный сокет для 203.0.113.16:80, последний думает, что общается с NAPT, и даже не знает о существовании 192.168.0.8:1234.
Так выглядит сеть из частной сети (он идентичен реальной сети):
А это вид для узлов во внешней сети:
Есть ещё несколько вещей, о которых вы, возможно, захотите знать о NAPT.
NAPT обычно разрабатывался с целью предоставления ограниченному набору клиентов (т. е. левой части - частной сети) доступа к любому количеству серверов (общедоступной правой части) по цене только одного общедоступного IPv4-адреса. Несколько неприятный результат заключается в том, что связь по умолчанию может быть запущена только из частной сети. Почему? Потому что при отсутствии состояния NAPT может иметь смысл исходя из исходящего адреса назначения, но не из входящего адреса назначения. Пакет 192.168.0.8:5000->203.0.113.16:80 просто направляется на 203.0.113.16:80, но NAPT не может знать, какому из частных узлов принадлежит входящий пакет 203.0.113.16:5000->203.0.113.1:80 (опять же, если предположить, что таблица сопоставлений пуста). По этой причине вам необходимо настроить переадресацию портов, если вы хотите, скажем, опубликовать HTTP-сервер за NAPT. Например, правило переадресации портов [192.168.0.8:80, 203.0.113.1:80] представляет собой статическую конфигурацию, которая постоянно резервирует маску 203.0.113.1:80 для службы 192.168.0.8:80 и позволяет доставлять пакеты через «NAT» даже при отсутствии динамического маршрута.
Во-вторых, количество общедоступных сокетов для маскировки, доступных для NAPT, ограничено 65536 на транспортный протокол (при условии, что вы не хотите исключать системные порты) на один общедоступный IPv4-адрес. Почему? Потому что и TCP, и UDP предоставляют 65536 портов для каждого IP-адреса. Это означает, что если ваш NAPT олицетворяет 130 частных узлов и имеет только один публичный IPv4-адрес, то каждый из них может одновременно иметь не более 500 (65536 разделить на 130) сокетов, по крайней мере, для связи с узлами через NAPT. Это ограничение не очень заметно для NAPT, поскольку оно часто используется для обслуживания сетей с ~10 или даже ~20 устройствами, взаимодействующими с Интернетом, но оно может стать более насущным вопросом в зависимости от того, что вы хотите делать со своим Stateful NAT64.
Stateful NAT64
NAT64 с отслеживанием состояния (далее для простоты просто «NAT64») почти такой же, как NAPT. Единственное отличие состоит в том, что «Частная сеть» на самом деле является сетью IPv6:
Как только приходит исходящий пакет, его исходный адрес транслируется точно так же, как в NAPT, тогда как его адрес назначения транслируется в соответствии с pool6:
Внутри всё работает аналогично NAPT:
Применение:
NAT64 полезен, когда у вас есть определенное большое количество узлов IPv6 (т. е. ограниченное количеством транспортных адресов, доступных для «T»), желающих взаимодействовать с любым количеством узлов IPv4.
Так что это похоже на традиционный SIIT на стероидах, за исключением того, что необходимо использовать таблицу трансляции.
Сеть со стороны протокола IPv6:
Сеть со стороны протокола IPv4:
По сути, Stateful NAT64 похож на SIIT, но имеет все преимущества и недостатки NAPT. Вы можете представить все свои узлы IPv6 как можно меньшим количеством адресов IPv4, но вы ограничены 65536 подключениями на общедоступные адреса IPv4, а при отсутствии переадресации портов все коммуникации должны инициироваться со стороны IPv6.
Вы также можете провести сравнение с SIIT-DC. В некотором смысле Stateful NAT64 — это своего рода обратный SIIT-DC: первый чувствует себя как дома, когда у вас есть несколько клиентов IPv6, которым требуется доступ к любому количеству интернет-серверов IPv4, в то время как второй более подходит, когда у вас есть несколько серверов IPv6, к которым должны обращаться любые интернет-клиенты IPv4.
В контексте NAT64 обычно не называют сеть IPv6 «частной», потому что она также должна быть подключена к интернету по IPv6:
Таким образом, узлы от «A» до «E» имеют только IPv6, но они имеют доступ в интернет по обоим протоколам: IPv6 через маршрутизатор «R» и IPv4 через «T».
NAT64 с отслеживанием состояния описан в RFC 6146 и связан с DNS64.
464XLAT
464XLAT — это, по сути, SIIT-DC-2xlat, где BR — это Stateful NAT64, а не SIIT.
В контексте 464XLAT ER называется CLAT («Customer-side Translator»), а BR — PLAT («Provider-side Translator»).
Просто для ясности: PLAT — это Stateful NAT64. CLAT по-прежнему остается SIIT. Поскольку соединения Stateful NAT64 должны инициироваться со стороны IPv6, для CLAT не имеет смысла использовать NAT64.
Применение:
Кода это может быть полезным? Если вы интернет-провайдер, вы можете использовать 464XLAT, чтобы предоставить своим клиентам Интернет IPv4 фактически не имея IPv4 в своей инфраструктуре. «Остров IPv4» находится у клиента, CLAT — его домашний маршрутизатор.
Если вы не являетесь интернет-провайдером, вы все равно можете использовать 464XLAT, если у вас есть шлюз NAT64 для ресурсов интернет с IPv4, но некоторые из ваших приложений на стороне IPv6 по-прежнему не поддерживают IPv6. Как и в случае с SIIT-DC-2xlat, речь идет об инфраструктуре, в основном IPv6, с небольшими островками IPv4. 464XLAT для NAT64 — это то же самое, что SIIT-DC-2xlat для SIIT-DC.
MAP-T
Предположим, вы являетесь интернет-провайдером (ISP) с 4 клиентами, но у вас есть только один бесплатный IPv4-адрес для распределения между ними.
Идея MAP-T состоит в том, чтобы «разделить» ваш адрес IPv4 на равные части и дать каждую часть отдельному клиенту (и сделать остальную часть вашей инфраструктуры только на IPv6).
Как вы «разделите» адрес IPv4? Помним, что каждый адрес имеет 65536 портов на транспортный протокол:
Конечно, физически невозможно назначить часть IPv4-адреса узлу, здесь и приходят на помощь трансляторы MAP:
Примечание. Эти фрагменты адресов физически не назначаются конечным узлам. Обратите внимание, что облако интернет-провайдера по-прежнему использует только IPv6.
Customer Edges (CEs) и Border Relays (BRs), как обычно, следят за тем, чтобы все общались именно теми протоколами, которые они умеют использовать.
Каждый клиент будет использовать частные адреса (192.168.x.y), а каждый CE будет состоять из традиционного NAPT, привязанного к транслятору. NAPT сократит частное адресное пространство до назначенного фрагмента, а транслятор преобразует полученный пакет во что-то, что может пройти по сети IPv6.
Вот пример. Предположим, мы решили зарезервировать подсеть 2001:db8:ce::/48 для всех наших нужд CE и используем 64:ff9b:1::/96 для маскировки интернета IPv4. Клиент 192.168.0.4 находится за CE, который владеет частью 2 (порты 32768-49151) (и, следовательно, владеет префиксом 2001:db8:ce:2::/64), и хочет отправить пакет на HTTP-сервер IPv4 203.0.113.56 в интернете.
Пакет сначала получает NAPT с частного адреса IPv4 на псевдослучайный общедоступный адрес IPv4, который может использоваться CE.
Если вы никогда не использовали NAPT в сокращенном диапазоне портов, вы можете быть уверены, что это совершенно обычная операция Stateful NAT. Пакет уже был бы маршрутизируемым, если бы у нас была сеть IPv4.
После этого пакет корректно проходит MAP-T. Адрес источника содержит идентификатор группы CE, а pool6, как обычно, добавляется к адресу назначения, если говорить упрощенно.
BR выполняет обратное преобразование того, что сделал CE, но не часть NAPT.
Сервер отвечает. BR применяет соответствующее преобразование к каждому адресу.
Вы можете задаться вопросом: поскольку все CE технически владеют адресом 192.0.2.1, как BR узнает, что предполагаемый CE — это 2, а не один из других? Потому что по конфигурации BR знает, что порт 40000 принадлежит группе 2.
Затем пакет направляется к CE, которому принадлежит префикс, которому он предназначен. Всё заканчиваются тем, что всё будет происходить в обратном порядке.
Конечно, хотя MAP-T — это метод, в первую очередь связанный с передачей трафика IPv4 через магистраль IPv6, ничто не мешает вам также назначать IPv6-адреса вашим клиентам и направлять этот трафик в обычном режиме (через маршрутизатор R6).
Так чего же мы добились этим псевдо запутанным обращением с адресами? Что ж, мы собрали 464XLAT, в котором PLAT не имеет состояния. Кроме того, интересно отметить, что, поскольку фрагменты предварительно распределены, один злоумышленник не может исчерпать весь ресурс адреса общественного транспорта; они бы только исчерпали свой собственный.
Таблица сравнения разного вида трансляции:
464XLAT | MAP-T |
---|---|
Законы вашей страны могут заставить вас вести журналы сеансов. | Нет необходимости ведения журналов т.к. все соединения определены в конфигурации. |
PLAT назначает клиентам адреса транспорта по запросу. Клиенты, которым потребуют больше ресурсов, могут получить больше за счёт того, что другие получат меньше. | Всем присваивается одинаковое строго отведённое количество ресурсов. |
Один клиент может выполнять DoS атаку для других клиентов, исчерпав пул ресурсов транспорта PLAT. | Один клиент не может запросить бо́льшую часть доступного ресурса, потому что уже имеет строго отведённую ему часть в соответствии с конфигурацией. |
MAP-T формально описан в RFC 7599 и, в значительной степени, в RFC 7597.
Обратите внимание, что заметки могут обновляться со временем. Это может быть как исправление найденных ошибок, так и доработка содержания с целью более полного раскрытия темы. Информация об изменениях доступна в репозитории на github. Там же вы можете оставить в Issue ваши замечания по данной заметке.
Если данная заметка оказалась вам полезной, можете поблагодарить автора финансово.