Qeli 0.8.2 · dual-stack и routed IPv6

IPv6 и dual-stack в Qeli

Внешний IPv4/IPv6 carrier, внутренний NetworkPlan v2, ULA/GUA, NAT66 или маршрутизация, встроенный NDP proxy для on-link префиксов, DNS, MTU и безопасная миграция.

Два уровня

Внешний carrier и внутренний TUN независимы

Начиная с 0.8.0 Qeli разделяет семейство соединения с сервером и семейства пакетов внутри туннеля. bind/listen/server могут использовать IPv4, IPv6 или hostname с A/AAAA, а tun.ip_mode, пулы и аутентифицированный NetworkPlan определяют внутренний IPv4/IPv6 data plane.

IPv4-carrier может переносить внутренний IPv6, а IPv6-carrier — внутренний IPv4. IPv6-literal в клиентском INI всегда пишется со скобками: server = [2001:db8::10]:443.
Провайдер выдал отдельный публичный on-link префикс? Перейдите к разделу «NDP proxy: настройка и проверка» — там есть схема работы, полный конфиг и диагностика через tcpdump.
Режим профиля

tun.ip_mode = ipv4 | dual | ipv6

РежимЧто получает клиентПрименение
ipv4IPv4 lease, маршруты и DNS.Совместимость или сервер без готового IPv6 uplink.
dualНезависимые IPv4 /32 и IPv6 /128 на L3 TUN, оба набора маршрутов и DNS.Рекомендуемый обычный режим.
ipv6Только IPv6 lease и план.Специализированная IPv6-only сеть; доступа к IPv4-only сервисам без отдельного NAT64 не будет.

NetworkPlan v2 отдельно передаёт assigned address, on-link prefix и gateway для каждого семейства и применяется атомарно. Полуприменённый план не считается успешным подключением.

Базовый профиль

Минимальный dual-stack пример

server.conf · [profile:main]
tun.ip_mode = dual
tun.name = vpn0
tun.address = 10.19.0.1
tun.ipv6_address = fd71:e1:8000:102::1
tun.mtu = 1400
tun.device_type = tun

pool.cidr = 10.19.0.0/24
pool.ipv6.cidr = fd71:e1:8000:102::/64

routing.nat.enabled = true
routing.ipv6.mode = nat66

dns.enabled = true
dns.listen = 10.19.0.1
dns.listen_ipv6 = fd71:e1:8000:102::1
dns.push_servers = 10.19.0.1, fd71:e1:8000:102::1

Используйте уникальный для развёртывания RFC 4193 ULA /48 и отдельный /64 на профиль. Не копируйте пример fd71:… буквально между независимыми установками и не используйте link-local fe80::/10 как пул. Quick Start генерирует случайный 40-битный Global ID.

Выход и маршруты

routing.ipv6.mode

ЗначениеЧто делаетТребованияNDP proxy
offБлокирует IPv6-транзит между TUN профиля и другими интерфейсами в обе стороны.Рабочий ip6tables нужен, чтобы DROP был гарантирован.Только off
manual · 0.8.2IPv6 firewall и forwarding настраивает администратор; NDP можно включить отдельно.Ручная маршрутизация, DNS-доступ и изоляция. ip6tables не требуется.off, auto, required
routeНастраивает пересылку с сохранением исходного IPv6 клиента.Для выхода в интернет — маршрутизируемый провайдером GUA-префикс и обратный маршрут. Для LAN/site-to-site достаточно маршрутов между своими сетями.off, auto, required
nat66Настраивает пересылку и NAT66 через IPv6 WAN сервера.IPv6 default route, публичный GUA из 2000::/3 и рабочий ip6tables NAT. Удобно на обычном VPS, но это NAT.Только off
Не используйте WAN /64, уже назначенный uplink-интерфейсу, как клиентский pool. Нужен отдельный routed или отдельный on-link префикс; для второго в 0.8.1 доступен session-aware NDP proxy.

Для routed GUA задавайте reservation или static_ipv6; CLI поддерживает qeli add-client --static-ipv6 ….

Ручное управление IPv6 · 0.8.2

manual требует сборки 0.8.2 с поддержкой этого режима; бинарник 0.8.1 его не распознаёт. Пример ниже — фрагмент существующего INI-профиля с tun.ip_mode = dual или ipv6 и уже настроенными IPv6 gateway/pool.

Если маршрутизацией и firewall управляет firewalld или native nftables, используйте routing.ipv6.mode = manual. Qeli продолжает создавать туннель, назначать адреса и обслуживать клиентские маршруты и NDP. Он не устанавливает IPv6-правила транзита, MSS, DNS INPUT/REDIRECT и не включает forwarding/accept_ra. Для этого режима ip6tables не требуется; IPv4 настраивается независимо.

INI · ручной IPv6 и обязательный NDP
routing.ipv6.mode = manual
routing.ipv6.interface = ens3
routing.ipv6.ndp_proxy = required
routing.ipv6.ndp_proxy_interface = ens3

Администратор обеспечивает forwarding, обратные маршруты, изоляцию профилей, ICMPv6 и доступ UDP/TCP к встроенному DNS. При dns.port != 53 он также настраивает IPv6-перенаправление порта 53. При смене режима Qeli убирает собственные старые правила и освобождает sysctl-аренды; настройки хоста должны существовать независимо. required по-прежнему отклоняет запуск при ошибке responder. off сохраняет блокировку IPv6-транзита.

required проверяет привязку responder к интерфейсу; успешный запуск не гарантирует правильную ручную маршрутизацию или firewall. Для обычного routed prefix без NDP используйте ndp_proxy = off.

  1. Подготовьте постоянные настройки forwarding, обратных маршрутов, firewall, ICMPv6, RA и DNS.
  2. В панели выберите Config → профиль → Routing → IPv6 forwarding / NAT66 → manual. Настройте Upstream IPv6 NDP proxy и интерфейс согласно топологии.
  3. Для правки файла выполните qeli check-config --config /etc/qeli/server.conf, затем перезапустите сервис; в панели используйте Apply & Restart.
  4. После перезапуска проверьте forwarding/RA, IPv6-доступ и DNS по UDP/TCP; при NDP — ответ для активного клиента со стороны uplink.

Переход route ↔ manual в форме сохраняет NDP. Выбор off или nat66 выключает NDP и очищает его интерфейс. В INI установите routing.ipv6.ndp_proxy = off самостоятельно: несовместимые сочетания отклоняются.

Команды ниже используют qeli.service, которую создаёт стандартный установщик/DEB. Если вы создали службу под другим именем, замените qeli на имя своей службы.

Публичный IPv6 без NAT66 · 0.8.1

NDP proxy: когда нужен и как настроить

NDP (Neighbor Discovery Protocol) в IPv6 выполняет в том числе задачу, похожую на ARP в IPv4: соседний маршрутизатор отправляет Neighbor Solicitation (NS) и спрашивает, какой MAC-адрес обслуживает конкретный IPv6. Адрес VPN-клиента находится на TUN, а не на WAN-интерфейсе сервера, поэтому при on-link префиксе Qeli отвечает upstream-маршрутизатору сообщением Neighbor Advertisement (NA) с MAC-адресом сервера и затем маршрутизирует пакет в активную VPN-сессию.

Это не NAT66. Исходный публичный IPv6 клиента сохраняется. NDP proxy нужен только тогда, когда провайдер считает отдельный клиентский префикс непосредственно подключённым к своему L2-сегменту. Если провайдер создал обычный L3-маршрут префикса через WAN-адрес сервера, оставьте routing.ipv6.ndp_proxy = off.

Выберите режим по топологии провайдера

Что делает провайдерПризнакНастройка Qeli
Маршрутизирует отдельный префикс через WAN-адрес сервераДля клиентских адресов на WAN не приходят NS; в панели провайдера указан route/next hop.routing.ipv6.mode = route
routing.ipv6.ndp_proxy = off
Считает отдельный префикс on-linkНа WAN приходят NS для каждого публичного IPv6 клиента.routing.ipv6.mode = route
routing.ipv6.ndp_proxy = required
Топология пока неизвестнаНет точного описания у провайдера.Сначала проверьте трафик через tcpdump. auto допустим для диагностики, но для рабочей on-link схемы используйте required.

Как понять, нужен ли proxy

Не назначайте клиентский префикс WAN-интерфейсу. Остановите профиль или сервер, запустите захват на фактическом IPv6 uplink и с независимого внешнего IPv6-хоста обратитесь к будущему адресу клиента:

сервер Qeli и внешний IPv6-хост
# На сервере Qeli
$ sudo systemctl stop qeli
$ ip -6 addr show dev ens3
$ ip -6 route show table all
$ sudo tcpdump -ni ens3 'icmp6 && ip6[40] == 135'

# На внешнем IPv6-хосте
$ ping -6 2001:db8:1200:10::100

Строка Neighbor Solicitation, who has 2001:db8:1200:10::100 означает, что upstream ищет MAC для клиентского адреса и этой схеме нужен NDP proxy. Если NS нет, сначала проверьте правильность адреса, WAN-интерфейс, firewall/security group и условия провайдера: одно отсутствие пакета ещё не доказывает L3-routed схему.

Полный фрагмент профиля

Адреса 2001:db8::/32 ниже предназначены только для документации. Замените их отдельным GUA-префиксом, выданным провайдером для клиентов.

server.conf · [profile:public-v6-onlink]
[profile:public-v6-onlink]
tun.ip_mode = ipv6
tun.name = vpn-public
tun.ipv6_address = 2001:db8:1200:10::1
tun.mtu = 1280
pool.ipv6.cidr = 2001:db8:1200:10::/64

# Сохранять публичный IPv6 клиента; MASQUERADE не создаётся.
routing.ipv6.mode = route
routing.ipv6.interface = ens3
routing.ipv6.ndp_proxy = required
routing.ipv6.ndp_proxy_interface = ens3

Закрепите адрес за существующим пользователем

Отдельно откройте users.conf, указанный в [auth] users_file, и добавьте или измените static_ipv6 в существующей секции [user:alice]. Сохраните password_hash, enabled, группы и лимиты; не создавайте вторую секцию с тем же именем.

users.conf · [user:alice]
[user:alice]
# Существующие параметры пользователя сохраните.
static_ipv6 = 2001:db8:1200:10::100

Встроенные [user:*] в server.conf тоже поддерживаются, но при совпадении имени запись из users.conf имеет приоритет целиком. Поэтому настройка адреса только во встроенной записи не изменит существующую учётную запись из файла пользователей.

Не назначайте pool.ipv6.cidr интерфейсу ens3 и не создавайте для него connected route через WAN. Маршрут клиентского префикса должен вести только в TUN профиля; upstream выполняет NDP со своей стороны. Для dual-stack замените tun.ip_mode = ipv6 на dual и сохраните существующие параметры IPv4.

Параметры и требования

РежимПоведение
offResponder выключен. Значение по умолчанию и правильный выбор для обычного L3-routed префикса.
autoПытается открыть responder. При неподходящем интерфейсе, отсутствии Ethernet или CAP_NET_RAW пишет предупреждение и продолжает работу без него.
requiredНе запускает профиль, пока responder не привязан к выбранному интерфейсу. Рекомендуется для рабочей on-link схемы.

Пустой routing.ipv6.ndp_proxy_interface использует фактический uplink из routing.ipv6.interface или IPv6 default route. Нужен Ethernet-совместимый Linux-интерфейс и право CAP_NET_RAW; обычный системный сервис Qeli уже запускается с необходимыми правами. NDP proxy поддерживает source-preserving режим route, а в разрабатываемой 0.8.2 — также manual. Сочетания с nat66 и off запрещены.

Какие адреса Qeli объявляет

  • Точный IPv6 lease активной сессии из pool.ipv6.cidr, включая static_ipv6.
  • Адреса внутри non-default IPv6 client_subnet, зарегистрированного за подключённым router/site-to-site клиентом.
  • Только адреса живых сессий: disconnect, revoke или замена сессии немедленно снимают ownership.
  • /0, link-local, multicast, неверные NS и посторонние target-адреса игнорируются. Qeli не превращает responder в общий multicast relay.

Проверка после запуска

конфигурация, журнал, маршрут и NDP
$ sudo qeli check-config --config /etc/qeli/server.conf
$ sudo systemctl restart qeli
$ sudo journalctl -u qeli -n 100 --no-pager | grep -F 'IPv6 NDP proxy'
$ ip -6 route show 2001:db8:1200:10::/64
$ sudo tcpdump -ni ens3 'icmp6 && (ip6[40] == 135 || ip6[40] == 136)'

При required журнал должен сообщить session-aware IPv6 NDP proxy active on 'ens3', а маршрут клиентского /64 — вести через vpn-public. Пока Alice отключена, новый NS для её адреса не получает NA. После подключения Qeli отвечает своим MAC, а внешний трафик направляется в её TUN-сессию. После отключения новые ответы прекращаются; старая запись в neighbor cache upstream может сохраняться до истечения своего таймера.

СимптомЧто проверить
required не запускает профильИмя uplink, Ethernet-тип интерфейса, root/CAP_NET_RAW и сообщение в journal.
В tcpdump нет NSПравильность адреса и WAN-интерфейса, provider route/security group; возможно, префикс уже маршрутизируется и proxy не нужен.
NS есть, но NA нет при подключённом клиентеФактически выданный static_ipv6, состояние сессии и попадание target в pool или активный client_subnet.
NA есть, но трафик не доходитМаршрут /64 в TUN, IPv6 forwarding, ip6tables/cloud firewall и firewall клиента.
auto запустился без NDPНайдите предупреждение NDP proxy auto mode is unavailable, исправьте причину и переключитесь на required.
Политика клиента

ipv6 = auto | required | off

ПолитикаРезультат
autoПринимает IPv4, dual или IPv6. Dual может безопасно понизиться до IPv4, если платформа не умеет полный IPv6-контракт.
requiredТребует внутренний IPv6 и fail-closed при старом сервере, IPv4-only профиле, MTU ниже 1280 или неполной поддержке платформы.
offПросит IPv4 у dual-профиля и отклоняет IPv6-only план.

В full-tunnel отсутствие одного семейства блокируется по умолчанию. allow_ipv6_leak=true или allow_ipv4_leak=true — явный escape hatch, разрешающий отсутствующему семейству идти физическим путём. Оба значения по умолчанию false.

DNS и MTU

Настройте оба семейства целиком

  • dns.listen и dns.listen_ipv6 должны совпадать с активными gateway-адресами профиля; dns.push_servers не должен раздавать недоступный listener.
  • IPv6 требует MTU не меньше 1280. Политика required отвергает меньший план, а PMTU probing подбирает безопасный carrier budget.
  • route, route_file, server push и ACL принимают IPv4/IPv6 CIDR, но применяются только для согласованного семейства.
  • Outer DNS для hostname endpoint может вернуть A и AAAA; roaming способен перенести сессию между семьями после аутентифицированной проверки пути.
Миграция

Старый конфиг не становится dual-stack автоматически

  1. Сделайте backup и обновите сервер до 0.8.2.
  2. Выберите уникальный ULA /64 либо получите у провайдера routed GUA-префикс.
  3. Добавьте tun.ip_mode, tun.ipv6_address, pool.ipv6.cidr, IPv6 DNS и routing.ipv6.mode.
  4. Выполните qeli check-config; для NAT66 дополнительно проверьте default route, публичный source GUA и ip6tables NAT.
  5. Оставьте клиентам ipv6=auto, проверьте IPv4 и IPv6 отдельно, затем при необходимости ужесточайте до required.
Установщик сохраняет active dual-stack только при подтверждённом IPv6 uplink и NAT; иначе создаёт безопасный активный IPv4-only профиль, а подготовленные IPv6 значения остаются для ручного включения после исправления uplink.
Границы

Чего Qeli не делает

  • Qeli не предоставляет NAT64/DNS64. IPv6-only клиент не откроет IPv4-only ресурс без отдельной NAT64-инфраструктуры.
  • Qeli не превращает случайный WAN /64 в клиентский pool: нужен отдельный routed/on-link префикс и корректный обратный путь.
  • IPv6 внутри туннеля не означает, что серверный uplink автоматически готов: проверяйте адрес, default route, firewall и обратный маршрут.
Первоисточники

Полная документация IPv6 0.8.2