Туннель поднят, wg show сообщает о недавнем рукопожатии, пинг до туннельного адреса сервера проходит, а дальше ничего не отвечает. Первый порыв — перегенерировать ключи или заново поделиться конфигурацией. Это меняет именно ту часть пути, которая уже доказанно работает.

Завершённое рукопожатие говорит, что стороны согласовали ключи, что UDP доходит до конечной точки и что криптографическая маршрутизация принимает пакет. Оно ничего не говорит о том, может ли пакет после этого покинуть сервер.

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

Что на самом деле доказывает рукопожатие

WireGuard — это протокол UDP, который устанавливает сеанс рукопожатием Noise, а затем шифрует пакеты для собеседника. Если wg show показывает рукопожатие давностью в несколько секунд и растущий счётчик передачи, то конечная точка, ключи и открытый ключ собеседника все верны.

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

Именно поэтому пинг до туннельного адреса сервера — такой обманчивый тест. Этот пакет адресован самому серверу, поэтому он завершается локально. Ему никогда не нужна пересылка, никогда не нужен перевод и никогда не нужен обратный маршрут из интернета.

AllowedIPs — это решение о маршрутизации

На клиенте AllowedIPs выполняет две задачи. Это таблица криптоключевой маршрутизации, которая решает, какие адреса назначения уходят в туннель этого собеседника, и это список адресов источника, которые собеседник примет от вас. Если в конфигурации клиента указан только 10.8.0.0/24, публичные назначения никогда не попадают в интерфейс, и ваш обычный маршрут по умолчанию уводит их мимо туннеля. Тогда туннель работает идеально и не делает ничего из того, что вы хотели.

Смотрите на то, что клиент действительно установил, а не на то, что написано в файле конфигурации:

wg show wg0 allowed-ips
ip route get 1.1.1.1

Вторая команда — решающая. Если в ответе названы ваш физический интерфейс и обычный шлюз, пакет не идёт через туннель, и никакое изменение на стороне сервера это не исправит. Добавьте 0.0.0.0/0 для IPv4 и ::/0 для IPv6 отдельно; правило, охватывающее всё для одного семейства, оставляет другое на прежнем пути, и это частая причина работающего туннеля IPv4 и застрявшего поиска IPv6.

Где пакет погибает на шлюзе

Если маршрут верен, а пакет всё равно никуда не идёт, он доходит до сервера и останавливается там. Четыре проверки охватывают большинство шлюзов.

Пересылка. sysctl net.ipv4.ip_forward с ответом 0 — классический случай, и многие дистрибутивы до сих пор по умолчанию стоят на 0. Должно быть 1, и задавать это нужно постоянно в файле sysctl, а не командой, которая исчезает при перезагрузке. Пересылка IPv6 — отдельный переключатель.

Политика фильтрации. Цепочка FORWARD с политикой по умолчанию на сброс будет выбрасывать туннельный трафик, но пропускать трафик к самому хосту, и это точно совпадает с симптомом. Читайте живой набор правил, а не сохранённый файл: nft list ruleset или iptables -S.

Трансляция или маршрутизация. Клиентам с частными туннельными адресами нужен либо NAT источника на выходном интерфейсе сервера, либо маршрутизируемый префикс, который вышестоящая сеть умеет возвращать. Выбор между ними следует плану адресов. Добавить MASQUERADE в сеть, которая уже маршрутизирует ваш префикс назад, безвредно, но бессмысленно, а пропуск там, где маршрута нет, оставляет ответы с адресом в недостижимом частном диапазоне.

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

DNS отказывает иначе, чем маршрутизация

Пакет на известный адрес и поиск имени — две разные неисправности, и сообщения об ошибках вводят в заблуждение в противоположных направлениях. Если ping 1.1.1.1 работает, а браузер ничего не загружает, маршрут в порядке, а разрешение имён — нет. Если сам пинг не проходит, DNS ни при чём, и вы вернулись к предыдущему разделу.

wg-quick может задать резолвер из строки DNS = в конфигурации, а у systemd-resolved своё поведение для каждого соединения. VPN, который перезаписывает резолвер адресом, доступным только внутри туннеля, провалит каждый запрос в момент падения туннеля, и это выглядит так, будто туннель ломает интернет.

SymptomLayer to inspect
Tunnel address pings, nothing else doesClient route, then gateway forwarding
Public IP pings, hostnames failResolver selection and reachability
Handshake completes, no reply everFORWARD policy or missing NAT on the server
Small requests work, large transfers stallMTU and TCP MSS clamping

Порядок, который даёт доказательства

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

На сервере следите за интерфейсом, пока отправляете пинг с клиента: tcpdump -ni wg0 icmp должен показать запрос, а tcpdump -ni eth0 icmp — что он уходит, переведённый или нет. Если он появляется на первом и никогда на втором, остановка локальна на сервере. Если он уходит, а ответ не возвращается, проблема выше, и это другой разговор.

В конце сделайте так, чтобы исправление пережило перезагрузку. Пересылка относится к файлу sysctl, правила межсетевого экрана — к службе, которая их загружает, а маршруты клиента — к конфигурации, поднимающей интерфейс, а не к оболочке, которую вы забудете. Переподключитесь, повторите те же два теста и убедитесь, что счётчики двигаются.

Похожие статьи