Сайт FSA
31.08.2023

Сеть IPv6 с доступом к IPv4 (NAT64+DNS64)

О чём эта заметка

Во время перехода интернета с IPv4 на IPv6 необходимо как-то обеспечить работу сети с учётом сервисов, которые работают только по IPv4. Можно использовать дуалстэк, т.е. использовать внутри сети IPv4 и IPv6 адресации. Схема рабочая, но приводит к необходимости настраивать два протокола вместо одного, что в больших сетях может заметно добавить работы сетевым администраторам. При этом для внешних адресов IPv4, скорее всего, будет использован NAT.

Ещё один вариант перехода на IPv6 — это использовать в сети адресацию только IPv6. Все внутренние сервисы переводятся на него, а для доступа к внешним ресурсам IPv4 применяется трансляция NAT64. Схема работы незначительно отличается от первого варианта. Также используется NAT, хотя и другого типа, но при этом отпадает необходимость в настройке IPv4 во внутренней сети.

Нам необходимо как-то заставить приложения обращаться к некоторому виртуальному IPv6 адресу, который посредством NAT64 будет преобразован в IPv4 адрес. Самое простое, что можно сделать - изменить ответы DNS так, что при запросе записей типа A будут возвращаться также записи типа AAAA. Они должны указывать на адрес сервиса NAT64, который будет получать запросы и транслировать их в сеть IPv4.

Ограничения подобной схемы:

  1. При обращении по IPv4 адресу непосредственно, возникнет ошибка, т.к. протокол IPv4 не поддерживается сетевым интерфейсом хоста. У этой проблемы есть несколько решений, одно из которых установка специального сервиса непосредственно на клиентской машине, который преобразует запросы к адресам IPv4 в IPv6 по той же схеме, что используется в DNS64. Подробнее об этом читайте ниже.
  2. Если домен использует DNSSEC и не имеет записей AAAA, то наши «фейковые» AAAA записи не будут иметь корректной цифровой подписи. Это не очень критично, потому что узлов с DNSSEC и без записей AAAA (для которых будут создаваться фейковые AAAA записи) крайне мало. Если вы используете DNSSEC то вы должны обратить на это внимание и протестировать все необходимые вам внешние сервисы только с IPv4 и убедиться, что они не используют DNSSEC.

История решения задачи

Первые тесты с DNS64 и NAT64 я выполнял ещё в декабре 2022 года. При этом был использован стенд из трёх виртуальных машин на базе Virtualbox, две из которых выступали в качестве клиентов на базе Fedora 37 и Ubuntu 22.04 LTS. В качестве шлюза был использован Ubuntu 22.04 LTS. Всё необходимое ПО доступно из репозиториев, доступных в базовой поставке систем.

Сервер имеет два сетевых интерфейса, один из которых подключен к локальной сети, а второй к внутренней сети VirtualBox. Клиентские машины подключались только ко внутренней сети. Поскольку имеющийся маршрутизатор не позволял использовать выданную IPv6 адресацию от провайдера, то в качестве поставщика IPv6 использовался туннельный брокер с подключением через Wireguard. При таком подключении можно использовать как подключение виртуальной машины по умолчанию с использованием NAT, так и режим моста с сетевым интерфейсом реальной машины.

В дальнейшем я перешёл на тестирование на реальном железе. Сделать это мне позволил маршрутизатор с OpenWRT, который имеет все необходимые пакеты, чтобы обеспечить вашу сеть как режимом дуалсэк, так и полностью перевести её на IPv6.

Какой софт понадобится?

Для того, чтобы организовать вашу собственную сеть, которая использует только IPv6 протокол, нам необходимо обеспечить:

  1. преобразование записей DNS для IPv4 (типа A) в записи для IPv6 (AAAA);
  2. трансляцию адресов из IPv4 в IPv6 (NAT64):
  3. рассылку анонсов маршрутизатора в LAN.

Обеспечить преобразование записей DNS можно с помощью:

Трансляцию адресов NAT64 могут обеспечить:

TAYGA проще в установке, но при этом могут возникнуть проблемы с производительностью при большом количестве соединений. Jool требует установку модуля ядра, но при этом имеет хорошую производительность.

Рассылку объявлений маршрутизатора можно выполнить, например, с помощью сервиса radvd.

Подготовка к установке

Первое, что необходимо сделать, определиться с адресацией IPv6, которая будет использована для для механизма трансляции. Этот префикс необходимы выбирать исходя из адресации вашей сети. В качестве диапазона может быть использован глобально уникальный диапазон адресов или локально уникальный или префикс 64:ff9b::/96. Обратите внимание, что использование префикса 64:ff9b::/96 запрещает узлам IPv6 связываться с узлами IPv4, имеющими частные (RFC1918) адреса, в соответствии с RFC 6052. Глобально уникальный диапазон адресов позволит пользоваться вашим сервисом даже за пределами вашей сети или сделать его доступным для других пользователей сети Internet. Остальное доступно только в пределах локальной сети при настройке соответствующей маршрутизации.

В дальнейшем я буду использовать диапазон 64:ff9b::/96.

Я пользуюсь провайдером «Ростелеком» который выделяет мне сеть /56. Однако префикс этой сети динамический, т.к. меняется периодически, арендованный маршрутизатор не умеет выдавать доступные мне подсети. Поэтому, для эксперимента я использовал туннельного брокера, который мне выделяет постоянную сеть /48. Позднее я заменил маршрутизатор, а старый использовал в режиме моста, что позволило мне по полной задействовать выданную мне провайдером сеть.

Выделим диапазон для нашей сети, которая будет пользоваться сервисами NAT64 и DNS64. Я буду использовать 2001:db8:feee:1::/64.

Внешний адрес сервера, который будет выполнять функции NAT64 будет 2001:db8:feee::2. Доступ в интернет он будет иметь через IPv4 10.0.2.15 (в моём случае это был VirtualBox с NAT).

В качестве DNS64 сервера можно выбрать как публичные DNS64, так и настроить собственный на базе Unbound или Bind. В качестве транслятора NAT64 можно выбрать Tayga или Jool. В дальнейшем приведены примеры настройки для всех пакетов, но на реальной машине понадобится только один для каждой функции.

Публичные DNS64 серверы

Если вы выбрали использовать диапазон 64:ff9b::/96, то вы можете обойтись без настройки сервера Bind и воспользоваться публичными DNS64 серверами. Их предоставляют, например, Google и Cloudflare. По сути это те же сервисы Google DNS и Cloudflare DNS, но для адресов, которые не имеют записей AAAA эти DNS предоставляют адрес из диапазона 64:ff9b::/96.

Адреса серверов Google DNS64:

Адреса серверов Cloudflare DNS64:

Оба сервиса поддерживают работу через безопасный транспорт DNSoverTLS и DNSoverHTTP. Google использует для этих служб сертификат домена dns64.dns.google.

Настройка Unbound (DNS64)

Необходимо включить модуль dns64 с помощью директивы module-config и указанию префикса, который будет использован с помощью dns64-prefix. Не забываем разрешить доступ к серверу с других хостов (interface) путём указания адресов или имён интерфейсов. Также необходимо указать пул адресов, для которого будет доступен сервер (access-control), например, для всех через IPv6 (::/0)

Можно просто создать файл в папке /etc/unbound/unbound.conf.d/, например, с именем dns64.conf и разместить в нём следующую информацию:

server:
    module-config: "dns64 validator iterator"
    dns64-prefix: 64:ff9b::/96
    interface: enp0s8
    interface: ::1
    access-control: ::/0 allow

Обратите внимание, что по умолчанию на сервере включены модули subnet, validator и iterator. При подобной конфигурации модуль subnet будет отключен.

В качестве интерфейсов указан сетевой интерфейс, который смотрит в локальную сеть и петлевой интерфейс ::1 для локальных подключений.

# nslookup 
> server ::1
Default server: ::1
Address: ::1#53
> habr.com
Server:  ::1
Address: ::1#53

Non-authoritative answer:
Name: habr.com
Address: 178.248.237.68
Name: habr.com
Address: 64:ff9b::b2f8:ed44

Сочетание опций interface и access-control может быть изменено в зависимости от ваших предпочтений и исходя из конфигурации вашей реальной сети. Они влияют только на доступность сервера, но не на механизм DNS64.

Настройка Bind 9 (DNS64)

Настройку можно начать с DNS. Bind 9 начиная с версии 9.8 позволяет использовать специальную опцию dns64, которую необходимо разместить в секции options:

options {
...
    dns64 64:ff9b::/96 {
        suffix ::;
        clients { any; };
        mapped { any; };
    };
};

Перезапускаем службу named. Теперь ответ от DNS сервера должен запись AAAA, которая указывает на адрес из выбранного диапазона. Проверим любой адрес, который не имеет записей AAAA в DNS, например, habr.com:

# nslookup
> habr.com
Server:  127.0.0.53
Address: 127.0.0.53#53

Non-authoritative answer:
Name: habr.com
Address: 178.248.237.68
Name: habr.com
Address: 64:ff9b::b2f8:ed44
>

При этом, если мы запрашиваем адрес, который уже имеет записи AAAA, то ответ не модифицируется:

> tavda.info
Server:  127.0.0.53
Address: 127.0.0.53#53

Non-authoritative answer:
Name: tavda.info
Address: 89.208.105.251
Name: tavda.info
Address: 2a0e:d602:1:f8::a

Настройка radvd

Настроим radvd для анонсов маршрутизатора. Используем выбранную сеть 2001:db8:feee:1::/64. В качестве DNS сервера будем предлагать 2001:db8:feee::2 - адрес нашего сервера-маршрутизатора.

interface enp0s8
{
    AdvSendAdvert on;
    MinRtrAdvInterval 30;
    MaxRtrAdvInterval 100;
    prefix 2001:db8:feee:1::/64
    {
        AdvOnLink on;
        AdvAutonomous on;
        AdvRouterAddr off;
    };
    RDNSS 2001:db8:feee::2 {
    };
};

Включение маршрутизации

Для включения маршрутизации необходимо включить передачу пакетов через хост через sysctl. В Ubuntu можно просто создать файл /etc/sysctl.d/99-route.conf:

net.ipv6.conf.all.forwarding = 1
net.ipv4.ip_forward = 1

После создания выполните sysctl --system или перезапустите систему. После этого ваш сервер сможет маршрутизировать пакеты IPv4 и IPv6.

Настройка TAYGA (NAT64)

Файл конфигурации TAYGA в Ubuntu расположен по пути /etc/tayga.conf. В нём необходимо выделить адреса IPv4 и IPv6, которые не будут совпадать с адресами хоста, а также пул адресов IPv4, который будет использован при трансляции:

tun-device nat64
ipv4-addr 10.0.2.129
ipv6-addr 2001:db8:feee::3
prefix 64:ff9b::/96
dynamic-pool 10.0.2.128/25
data-dir /var/spool/tayga

Наиболее значимые опции, которые необходимо изменить под свою сеть:

Подробнее смотрите в переводе комментариев из файла конфигурации TAYGA.

Настройка Jool (NAT64)

Ещё одним вариантом трансляции адресов является Jool. Он работает на уровне ядра, поэтому должен показывать большую производительность. На ОС Ubuntu начиная с 20.04 LTS и более поздних установить его можно с помощью команды

sudo apt install jool-dkms jool-tools

При этом будет установлена не самая свежая версия пакета. Можно воспользоваться репозиторием или собрать исходный код самостоятельно. Подробнее об этом можно почитать на сайте Jool. Однако версии, поставляемой с Ubuntu 22.04 LTS будет вполне достаточно для дальнейшего использования.

Запустить трансляцию адресов NAT64 вручную можно с помощью команды

sudo jool instance add "nat64" --netfilter --pool6 64:ff9b::/96

Здесь также указан диапазон 64:ff9b::/96, который можно заменить любым другим желаемым.

Остановка трансляции:

jool instance remove "nat64"

Для обеспечения автоматического запуска можно использовать юнит systemd. Для этого необходимо создать файл конфигурации формата JSON по адресу /etc/jool/jool.conf:

{
    "comment": "Configuration for the systemd NAT64 Jool service.",
    "instance": "nat64",
    "framework": "netfilter",
    "global": {
        "comment": "Pool6 prefix",
        "pool6": "64:ff9b::/96"
    }
}

После этого можно активировать и запустить юнит:

sudo systemd enable --now jool

Использование DNS64 и NAT64 на реальном железе

Самое интересное исследование мне удалось провести только после приобретения маршрутизатора, на который можно установить OpenWRT. В своей базовой поставке он вполне может обеспечить вашу сеть дуалстэком. И это первое, что вам нужно сделать. Дальнейшие модификации не повлияют на вашу сеть до тех пор, пока вы не отключите выделение IPv4 адреса. Тестировать работу режима только IPv6 вы сможете на любом вашем устройстве, которое позволяет отключить получение IPv4 адреса.

Т.к. OpenWRT базируется на ядре Linux, то в качестве NAT64 можно использовать ранее упомянутый Jool:

opkg update
opkg install jool-tools-netfilter

Все настройки Jool находятся в папке /etc/jool/. Настройки, которые касаются NAT64, расположены в файле jool-nat64.conf.json. Изначально в нём содержится пример конфигурации. Можно заменить его самым простым вариантом, например:

cat << EOF > /etc/jool/jool-nat64.conf.json
{ "instance": "default", \
"framework": "netfilter", \
"global": { "pool6": "64:ff9b::/96" } }
EOF

Далее необходимо активировать Jool:

uci set jool.general.enabled="1"
uci set jool.nat64.enabled="1"
uci commit jool
/etc/init.d/jool restart

После этого можно проверить на клиенте, что все настройки произведены, например, так

ping 64:ff9b::8.8.8.8

Вы должны получить ответ от сервера 8.8.8.8. Можно использовать любой другой IP, который точно доступен и отвечает вашему маршрутизатору.

Теперь можно подключить DNS64 сервер и отключить IPv4 на клиенте. Я использовал DNS64 от Google. Естественно, для NAT64 был использован диапазон 64:ff9b::/96. Именно его подсказывает интерфейс LuCI на OpenWRT, а также он приведён в примере конфигурации. Другие устройства в сети имели доступ в интернет по обоим протоколам.

Что делать если приложению требуется IPv4

Решить эту проблему можно только непосредственно на клиенте. Для этого можно использовать компонент clatd. Он использует TAYGA при своей работе. Настраивать этот компонент почти не придётся. Достаточно прописать одну строку, где указать используемый в нашей сети префикс для трансляции NAT64. В файле /etc/clatd.conf добавим строку:

plat-prefix=64:ff9b::/96

После этого можно запустить сервис. После его запуска можно увидеть, что появился новый сетевой интерфейс clat.

# ip a
...
3: clat: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 500
    link/none
    inet 192.0.0.1/32 scope global clat
       valid_lft forever preferred_lft forever
    inet6 fe80::8617:661d:4056:8be3/64 scope link stable-privacy
       valid_lft forever preferred_lft forever

Теперь приложения, которые не используют DNS64 или обращаются в сеть по протоколу IPv4 смогут пользоваться интернет.

Вывод по результатам тестирования

С чем могут быть проблемы? Во-первых, это те программы, которые опираются на IPv4 адреса. Ранее были проблемы с запуском Steam, но новые версии уже не жалуются на недоступность сети.

Вторая явная проблема, которую я смог выявить уже на реальном железе: если у вас нет IPv4, то вам становятся недоступны пиры IPv4 по протоколу BitTorrent. Это не означает, что вам полностью закрыт доступ к торрентам, но это ограничивает вас только IPv6 пирами. Т.е. не стоит обрезать доступ к IPv4 вашему торрент клиенту. Если вы не можете использовать IPv4 совсем, то вы вполне можете воспользоваться сервисом clatd на своей машине. В Linux его нужно устанавливать и запускать. Слышал о том, что в MacOS он включается автоматически, если вы имеете доступ в сеть только IPv6. Для Windows решений пока не искал.

Третья проблема — кривые сайты. Как ни странно, но первый кривой сайт, с которым я столкнулся, был speedtest.net. Проблема в том, что он содержит AAAA записи в DNS, но по ним недоступен. При этом www.speedtest.net имеет только A записи и даже пытается загрузиться. Но, при этом, подгружает ресурсы со своих поддоменов, где тоже есть проблема с загрузкой по IPv6. Как результат, поехавшая вёрстка и полная неработоспособность сервиса. Если вы используете дуалстэк, то ваш браузер перейдёт на IPv4 и, единственно, что вас будет беспокоить, лёгкий дискомфорт, что сайт грузится медленно. Опять таки clatd вам поможет, поскольку позволит браузеру использовать Fallback режим, когда он обращается к IPv4, если сайт недоступен через IPv6.

Заключение

Уже в текущих условиях можно пользоваться исключительно IPv6 сетью на клиентских устройствах и иметь доступ практически ко всему, но при этом ваша сеть должна быть настроена должным образом.

Проблемы есть, и они незначительные. Корпоративные сети могут без проблем строиться исключительно на IPv6, что, даже, может добавить безопасности. К тому же всегда можно организовать островок IPv4 и через него организовывать доступ к нужным ресурсам по сети IPv6. Дома использовать только IPv6 может быть дискомфортно, особенно если вы любите качать торренты или играть в Steam игры (но это, возможно, уже решено), поэтому лучшим решением будет дуалстэк.


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


Если данная заметка оказалась вам полезной, можете поблагодарить автора финансово.