IPv6 и dual-stack в Qeli
Внешний IPv4/IPv6 carrier, внутренний NetworkPlan v2, ULA/GUA, NAT66 или маршрутизация, DNS, MTU, leak-контроль и безопасная миграция старого профиля.
Внешний carrier и внутренний TUN независимы
Начиная с 0.8.0 Qeli разделяет семейство соединения с сервером и семейства пакетов внутри туннеля. bind/listen/server могут использовать IPv4, IPv6 или hostname с A/AAAA, а tun.ip_mode, пулы и аутентифицированный NetworkPlan определяют внутренний IPv4/IPv6 data plane.
server = [2001:db8::10]:443.tun.ip_mode = ipv4 | dual | ipv6
| Режим | Что получает клиент | Применение |
|---|---|---|
ipv4 | IPv4 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 пример
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
| Значение | Что делает | Требования |
|---|---|---|
nat66 | Подменяет ULA-источник на IPv6 WAN сервера. | IPv6 default route, публичный GUA из 2000::/3 и рабочий ip6tables NAT. Удобно на обычном VPS, но это NAT. |
route | Сохраняет исходный IPv6 клиента. | Для выхода в интернет — маршрутизируемый провайдером GUA-префикс и обратный маршрут. Для LAN/site-to-site достаточно маршрутов между своими сетями. |
off | Не выпускает IPv6 из профиля и ставит fail-closed изоляцию. | Рабочий ip6tables нужен, чтобы DROP был гарантирован. |
Для routed GUA задавайте reservation или static_ipv6; CLI поддерживает qeli add-client --static-ipv6 ….
routing.ipv6.ndp_proxy = off | auto | required
Предпочтительная схема — провайдер маршрутизирует отдельный клиентский префикс на WAN-адрес сервера. В ней оставьте off. Если провайдер считает отдельный префикс on-link и отправляет Neighbor Solicitation для каждого адреса, включите встроенный session-aware responder.
routing.ipv6.mode = route
routing.ipv6.interface = ens3
routing.ipv6.ndp_proxy = required
routing.ipv6.ndp_proxy_interface = ens3| Режим | Поведение |
|---|---|
off | Дефолт. Правильный выбор для обычного L3-routed префикса. |
auto | Пытается открыть responder; при неподходящем интерфейсе, отсутствии Ethernet или CAP_NET_RAW предупреждает и продолжает без него. |
required | Не запускает профиль, пока responder не привязан к выбранному интерфейсу. |
Responder отвечает MAC-адресом сервера только за точный IPv6 lease живой сессии и адреса внутри активного non-default client_subnet. Disconnect, revoke или замена сессии снимают ownership немедленно; /0, link-local, multicast, неверные NS и чужие адреса игнорируются.
route, не с nat66 или off.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.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 автоматически
- Сделайте backup и обновите сервер до 0.8.1.
- Выберите уникальный ULA /64 либо получите у провайдера routed GUA-префикс.
- Добавьте
tun.ip_mode,tun.ipv6_address,pool.ipv6.cidr, IPv6 DNS иrouting.ipv6.mode. - Выполните
qeli check-config; для NAT66 дополнительно проверьте default route, публичный source GUA и ip6tables NAT. - Оставьте клиентам
ipv6=auto, проверьте IPv4 и IPv6 отдельно, затем при необходимости ужесточайте доrequired.
Чего Qeli не делает
- Qeli не предоставляет NAT64/DNS64. IPv6-only клиент не откроет IPv4-only ресурс без отдельной NAT64-инфраструктуры.
- Qeli не превращает случайный WAN /64 в клиентский pool: нужен отдельный routed/on-link префикс и корректный обратный путь.
- IPv6 внутри туннеля не означает, что серверный uplink автоматически готов: проверяйте адрес, default route, firewall и обратный маршрут.