Ошибка WireGuard handshake failed указывает на неудачное квитирование между пирами, из-за чего VPN-туннель не поднимается. В этой статье разобраны основные причины, этапы диагностики и способы возврата стабильного соединения без привязки к конкретному провайдеру.
Разберём, почему возникает WireGuard handshake failed, какие проверки стоит выполнить сначала и в каком порядке лучше устранять проблему.
Что означает WireGuard handshake failed
Разберём, почему возникает WireGuard handshake failed, какие проверки стоит выполнить сначала и в каком порядке лучше устранять проблему.
Основные причины
| Причина | Что это значит |
|---|---|
| Несовпадение публичных ключей | Приватный ключ одного пира не соответствует публичному ключу, указанному на стороне второго пира. WireGuard проверяет подписи при рукопожатии, и при расхождении соединение сбрасывается. |
| Закрыт UDP-порт на одном из пиров | WireGuard использует указанный в конфигурации порт (по умолчанию 51820/udp). Межсетевой экран, NAT без проброса или провайдерская блокировка могут препятствовать прохождению пакетов квитирования. |
| Расхождение Endpoint и реального IP-адреса | Если один из пиров изменил внешний IP, а в конфиге второго остался старый Endpoint, пакеты уходят в неверном направлении, и рукопожатие не завершается. |
| Заблокированные протоколы на уровне провайдера | Некоторые операторы блокируют WireGuard-трафик по паттернам в заголовках пакетов Initiation и Response. При глубокой инспекции пакетов handshake прерывается. |
| Некорректные настройки AllowedIPs | Если сетевые префиксы в AllowedIPs не пересекаются или не включают IP удалённого пира, ядро может отбросить ответный handshake, так как маршрут до источника не соответствует разрешённым. |
| Разница в системных часах | Протокол использует временные метки для защиты от повторов. Расхождение более чем на несколько секунд между пирами способно привести к отклонению сообщения рукопожатия. |
| Ошибка PersistentKeepalive для полустатических соединений | При отсутствии keepalive за NAT время жизни привязки истекает, и ответный пакет handshake не доходит до инициатора, если не настроен периодический трафик для поддержания сессии. |
| Конфликт интерфейсов или таблиц маршрутизации | Если на хосте задействована политика маршрутизации (ip rule) или собственные таблицы, отличные от main, ответные пакеты могут уходить через другой интерфейс без шифрования, и рукопожатие не фиксируется. |
Что проверить сначала
- Сравните публичный ключ на каждом пире с соответствующим приватным ключом при помощи команды wg show
- Проверьте доступность UDP-порта удалённого пира утилитами nc или telnet (nc -u )
- Убедитесь, что Endpoint в конфигурации совпадает с актуальным внешним IP адресата (например, curl ifconfig.me на удалённой машине)
- Проверьте логи файрвола (iptables/ufw/firewalld) на предмет блокировки порта WireGuard
- Запустите tcpdump на обоих пирах для перехвата пакетов на порту WireGuard и проанализируйте, проходят ли Initiation и Response
- Сравните системное время на обеих сторонах командой date; разница не должна превышать 1-2 секунды
- Убедитесь, что в маршрутизации нет дублирующих или более специфичных правил, перехватывающих трафик к Endpoint
- Проверьте корректность AllowedIPs – в удалённую конфигурацию должен входить IP, с которого ожидается handshake
- Протестируйте соединение с временным отключением всех политик ip rule и дополнительных таблиц маршрутизации
- Убедитесь, что MTU на туннельном интерфейсе не занижен (стандарт 1420 для WireGuard), что может фрагментировать пакеты и мешать handshake
Пошаговое решение
- Сверьте ключевую пару: на каждом пире выведите публичный ключ (wg show) и сравните с записью в секции [Peer] противоположной стороны. При несовпадении сгенерируйте новые ключи и обновите конфигурации.
- Проверьте сетевую связность: с инициатора выполните ping до IP из Endpoint, затем проверьте прохождение UDP-пакетов утилитой nc (nc -zvu ). Если порт закрыт, настройте проброс или откройте доступ в фаерволе.
- Обновите Endpoint: если удалённый пир получил динамический IP, скорректируйте Endpoint в локальном конфиге, либо используйте динамический DNS.
- Настройте правила файрвола: добавьте правило для приёма пакетов на порт WireGuard (например, ufw allow 51820/udp) и разрешите маршрутизированный трафик, если пир является шлюзом.
- При подозрении на DPI провайдера смените стандартный порт WireGuard на менее распространённый (например, 41194/udp) и обновите конфигурации.
- Настройте синхронизацию времени: установите NTP-клиент (chrony или systemd-timesyncd) и убедитесь, что смещение стабильно менее 500 мс.
- Включите PersistentKeepalive = 25 секунд в секции пира, который находится за NAT, для поддержания привязки на маршрутизаторе.
- Исправьте AllowedIPs: если пир должен принимать только трафик конкретной подсети, укажите её, но обязательно включите IP или сеть, из которой приходит handshake. Часто помогает временно задать 0.0.0.0/0 для проверки, но не забывайте вернуть ограниченные префиксы после теста.
- Упростите маршрутизацию: на время диагностики удалите пользовательские таблицы ip rule и убедитесь, что маршрут к Endpoint проходит через основной интерфейс. Если проблема исчезает, добавляйте политики по одной.
- Проверьте MTU: на туннельном интерфейсе установите значение 1420 (ip link set dev wg0 mtu 1420) и убедитесь, что по пути нет дропа фрагментированных пакетов.
- Перезапустите интерфейс WireGuard после всех изменений командой wg-quick down wg0 && wg-quick up wg0 и отслеживайте handshake в логах wg show.
- Анализируйте дампы tcpdump: на обоих пирах запустите tcpdump -i any udp port -n и проверьте, видны ли пакеты Initiation и Response. Отсутствие Response указывает на проблему на стороне ответчика.
Проверить проблему WireGuard
Введите ошибку, симптом или часть конфигурации: handshake, AllowedIPs, DNS, MTU, Endpoint.
FAQ
Что значит handshake failed в выводе wg show?
Это означает, что последнее квитирование не было успешно завершено. В выводе будет отображаться «0 minutes» или «0 seconds» с момента последнего handshake для проблемного пира.
Достаточно ли просто перезапустить интерфейс, чтобы исправить ошибку?
Перезапуск сбрасывает состояние, но если причина не устранена, handshake снова не сработает. Рекомендуется сначала проверить ключи, порты и связность.
Может ли ошибка возникать из-за двойного NAT?
Да, двойной NAT усложняет прохождение ответных пакетов. Помогает настройка PersistentKeepalive и явный проброс порта на обоих маршрутизаторах.
Влияет ли версия WireGuard на совместимость рукопожатия?
Формат handshake стабилен с ранних версий, но старые реализации ядра могут содержать ошибки. Рекомендуется использовать актуальные пакеты wireguard-tools и модуль ядра.
Что делать, если handshake периодически пропадает?
Настройте мониторинг стабильности соединения и проверьте логи на предмет флапа маршрутов. Часто помогает уменьшить интервал PersistentKeepalive до 15–20 секунд и убедиться в отсутствии регресса у провайдера.
Можно ли игнорировать ошибку, если туннель работает?
Если трафик проходит, а handshake failed отражается как статическая запись, возможно, данные устарели после успешного квитирования. Выполните wg show ещё раз – если время handshake обновляется, проблема решена, а надпись была просто артефактом предыдущего сбоя.
Итог
Ошибка WireGuard handshake failed почти всегда сводится к нескольким типовым причинам: несовпадение ключей, блокировка порта, неверный Endpoint, проблемы времени или фильтрация DPI. Последовательная проверка связности, ключей и маршрутизации позволяет быстро восстановить туннель. Для сложных случаев рекомендуется перехват трафика и анализ пакетов инициализации.