Утечка IPv6 через VPN: почему она возникает и как проверить маршрутизацию

VPN-туннель шифрует и перенаправляет трафик через удалённый сервер, скрывая реальный IP-адрес пользователя. Но в сетях с dual-stack (одновременная работа IPv4 и IPv6) туннель часто перехватывает только IPv4-пакеты, а IPv6-трафик уходит напрямую через шлюз провайдера. В результате удалённый сервер видит настоящий IPv6-адрес клиента, даже если IPv4 полностью скрыт за VPN.

Это не теоретическая проблема: большинство крупных провайдеров в Европе и Северной Америке уже раздают IPv6 по умолчанию, а многие мобильные операторы используют IPv6 как основной протокол. Если VPN-клиент не обрабатывает IPv6 явно, утечка происходит без какого-либо предупреждения.

Почему туннель пропускает IPv6​


Маршрутизация IPv4 и IPv6 в операционной системе управляется раздельными таблицами. Когда VPN-клиент поднимает туннельный интерфейс, он добавляет маршрут по умолчанию для IPv4 (например, 0.0.0.0/0 через tun0 или wg0), но не всегда делает то же самое для IPv6. Если в таблице маршрутизации IPv6 нет записи, направляющей трафик в туннель, ядро отправляет IPv6-пакеты через физический интерфейс напрямую.

Типичная ситуация:

  • VPN-сервер поддерживает только IPv4 внутри туннеля.
  • Клиент получает IPv6-адрес от провайдера через SLAAC или DHCPv6.
  • Таблица маршрутизации IPv6 содержит default route через физический шлюз.
  • Весь IPv6-трафик (DNS-запросы, HTTP, WebRTC) идёт мимо туннеля.

Даже если VPN-провайдер заявляет «защиту от утечек», это часто означает только блокировку IPv4-утечек и DNS-запросов. IPv6-компонент остаётся без внимания.

Механика на примере WireGuard​


WireGuard использует концепцию Cryptokey Routing: список AllowedIPs для каждого пира одновременно определяет, какие пакеты шифровать и отправлять в туннель (при исходящем трафике) и какие принимать из туннеля (при входящем). Это описано в документации проекта: при отправке пакетов AllowedIPs работает как таблица маршрутизации, при приёме — как список контроля доступа.

Типичная клиентская конфигурация WireGuard выглядит так:

INI:
[Interface]
PrivateKey = gI6EdUSYvn8ugXOt8QQD6Yc+JyiZxIhp3GInSWRfWGE=
ListenPort = 21841

[Peer]
PublicKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw=
Endpoint = 192.95.5.69:51820
AllowedIPs = 0.0.0.0/0

Запись AllowedIPs = 0.0.0.0/0 перехватывает весь IPv4-трафик. Но IPv6-адреса здесь не указаны — значит, IPv6-пакеты не попадают в туннель и уходят через физический интерфейс. WireGuard поддерживает любую комбинацию IPv4 и IPv6 в AllowedIPs, поэтому для полного перехвата нужно добавить ::/0:

INI:
AllowedIPs = 0.0.0.0/0, ::/0

Без этой записи утечка IPv6 гарантирована, если у клиента есть рабочий IPv6-адрес и маршрут по умолчанию.

Как обнаружить утечку​


Проверка через браузер​


Самый быстрый способ — открыть сайт, который показывает адрес, видимый сервером. Если рядом с IPv4-адресом VPN-сервера отображается ваш реальный IPv6-адрес, утечка подтверждена. Популярные сервисы для проверки: ipleak.net, ipv6leak.com, browserleaks.com. Они показывают не только IP, но и DNS-серверы, которые обрабатывают запросы (по теме DNS-утечек см. DNS leak: как VPN может скрыть IP, но выдать DNS-запросы, и как это проверить).

Проверка маршрутной таблицы в Linux​


До подключения к VPN:

Bash:
ip -6 route show default

Вывод покажет что-то вроде:

Код:
default via fe80::1 dev eth0 proto ra metric 100

После подключения к VPN выполните ту же команду. Если default route для IPv6 по-прежнему указывает на физический интерфейс (eth0, wlan0), а не на туннельный (wg0, tun0), IPv6-трафик не идёт через VPN.

Для WireGuard можно дополнительно проверить, какие адреса назначены интерфейсу:

Bash:
ip -6 addr show wg0

Если вывод пуст или содержит только link-local адрес, туннель не обслуживает IPv6.

Проверка в Windows​


Код:
Get-NetRoute -AddressFamily IPv6 -DestinationPrefix "::/0"

Команда показывает, через какой интерфейс идёт IPv6-трафик по умолчанию. Если это физический адаптер, а не VPN-интерфейс — утечка присутствует.

Тест с traceroute​


Утилита traceroute6 (Linux) или tracert -6 (Windows) позволяет увидеть, через какие узлы проходит IPv6-пакет. Если первый хоп — шлюз вашего провайдера, а не VPN-сервер, трафик не туннелируется.

Способы устранения​


Добавить IPv6 в AllowedIPs (WireGuard)​


Если VPN-сервер поддерживает IPv6 внутри туннеля, достаточно расширить AllowedIPs:

INI:
[Peer]
PublicKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw=
Endpoint = 192.95.5.69:51820
AllowedIPs = 0.0.0.0/0, ::/0

При этом сервер должен иметь IPv6-адрес на интерфейсе WireGuard и маршрутизировать IPv6-трафик дальше. Если сервер не поддерживает IPv6, этот вариант не сработает — пакеты будут шифроваться, но не найдут выхода на стороне сервера.

Отключить IPv6 на физическом интерфейсе​


Если VPN-сервер не поддерживает IPv6, самый надёжный вариант — полностью отключить IPv6 на уровне системы. Это гарантирует, что ни один IPv6-пакет не покинет машину.

Linux (sysctl, до перезагрузки):

Bash:
sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1

Для сохранения после перезагрузки добавьте строки в /etc/sysctl.d/99-disable-ipv6.conf:

Код:
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1

Linux (NetworkManager):

Bash:
nmcli connection modify "Имя_подключения" ipv6.method disabled

Windows:

Отключение IPv6 через свойства адаптера (снять галочку «IP версии 6 (TCP/IPv6)») или через реестр:

Код:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters
DisabledComponents = 0xFF (DWORD)

После изменения реестра требуется перезагрузка.

Отключение IPv6 на физическом интерфейсе — радикальная мера. Она может нарушить работу приложений, которые зависят от IPv6 (некоторые мессенджеры, сервисы с IPv6-only CDN). Используйте этот подход, если VPN не поддерживает IPv6 и альтернатив нет.

Блокировка IPv6 через firewall​


Вместо полного отключения можно заблокировать исходящий IPv6-трафик, который не идёт через туннель. Это более гибкий подход: IPv6 остаётся активным на интерфейсе, но пакеты не покидают машину.

nftables (Linux):

Bash:
nft add table ip6 filter
nft add chain ip6 filter output '{ type filter hook output priority 0; policy drop; }'
nft add rule ip6 filter output oifname "wg0" accept

Эти правила блокируют весь исходящий IPv6-трафик, кроме того, что идёт через интерфейс wg0. Замените wg0 на имя вашего туннельного интерфейса.

iptables (legacy):

Bash:
ip6tables -A OUTPUT -o wg0 -j ACCEPT
ip6tables -A OUTPUT -j DROP

Команды firewall немедленно влияют на сетевой трафик. Убедитесь, что имя интерфейса указано верно, иначе можно заблокировать весь IPv6, включая локальный.

Встроенная защита VPN-клиента​


Некоторые коммерческие VPN-клиенты (NordVPN, ExpressVPN, Mullvad) имеют опцию «IPv6 leak protection», которая автоматически отключает IPv6 или блокирует его при активном туннеле. Если такая опция есть — включите её. Но не полагайтесь на неё слепо: проверьте результат одним из способов выше.

Типичные ошибки​


ОшибкаПоследствие
AllowedIPs = 0.0.0.0/0 без ::/0 в WireGuardВесь IPv6 идёт мимо туннеля
VPN-сервер не имеет IPv6-адреса на туннельном интерфейсеДаже с ::/0 в AllowedIPs пакеты не маршрутизируются
Отключение IPv6 только на одном интерфейсеЕсли в системе несколько адаптеров, IPv6 может уйти через другой
Проверка утечки только по IPv4Утечка IPv6 не видна, если не запросить явно IPv6-ресурс
WebRTC в браузереМожет раскрыть локальный IPv6-адрес даже при работающем туннеле

Проверка после исправления​


После применения любого из методов выполните повторную проверку:

  1. Откройте ipleak.net или аналогичный сервис. Убедитесь, что в разделе IPv6 отображается адрес VPN-сервера или надпись «IPv6 not detected».
  2. Выполните ip -6 route show default (Linux) и подтвердите, что default route указывает на туннельный интерфейс или отсутствует.
  3. Если использовали firewall-правила, проверьте их: nft list ruleset или ip6tables -L -v.
  4. Протестируйте WebRTC: откройте browserleaks.com/webrtc и убедитесь, что локальный IPv6-адрес не отображается.

Если на всех этапах IPv6-адрес не виден или принадлежит VPN-серверу — утечка устранена.

Источники​


 
Назад
Верх Низ