Рукостискання WireGuard проходить, але інтернету немає: простежте шлях пакета
Рукостискання доводить лише ключі та доступність. Простежте один пакет від AllowedIPs через пересилання, NAT і зворотний маршрут, щоб побачити, де він зупиняється.
Тунель піднято, wg show повідомляє про недавнє рукостискання, пінг до тунельної адреси сервера проходить, а далі нічого не відповідає. Перший порив — перегенерувати ключі або знову поділитися конфігурацією. Це змінює саме ту частину шляху, яка вже доведено працює.
Завершене рукостискання каже, що сторони узгодили ключі, що UDP доходить до кінцевої точки і що криптографічна маршрутизація приймає пакет. Воно нічого не каже про те, чи може пакет після цього залишити сервер.
Тому простежте один пакет замість здогадів. Є чотири місця, де він може загинути, і кожне залишає свій слід.
Що насправді доводить рукостискання
WireGuard — це протокол UDP, який встановлює сеанс рукостисканням Noise, а потім шифрує пакети для співрозмовника. Коли wg show показує рукостискання давністю кілька секунд і зростаючий лічильник передачі, кінцева точка, ключі та відкритий ключ співрозмовника всі правильні.
Чого воно не доводить: що клієнт узагалі надсилає інтернет-трафік в інтерфейс, що сервер готовий його пересилати і що відповідь знайде зворотний шлях. Це рішення маршрутизації ядра та міжмережевого екрана, і ухвалюються вони поза тунелем.
Саме тому пінг до тунельної адреси сервера — такий оманливий тест. Цей пакет адресований самому серверу, тому він завершується локально. Йому ніколи не потрібне пересилання, ніколи не потрібен переклад і ніколи не потрібен зворотний маршрут з інтернету.
AllowedIPs — це рішення про маршрутизацію
На клієнті AllowedIPs виконує два завдання. Це таблиця криптоключової маршрутизації, яка вирішує, які адреси призначення йдуть у тунель цього співрозмовника, і це список адрес джерела, які співрозмовник прийме від вас. Якщо в конфігурації клієнта вказано лише 10.8.0.0/24, публічні призначення ніколи не потрапляють в інтерфейс, і ваш звичайний маршрут за замовчуванням виводить їх поза тунелем. Тоді тунель працює бездоганно і не робить нічого з того, чого ви хотіли.
Дивіться на те, що клієнт справді встановив, а не на те, що написано у файлі конфігурації:
wg show wg0 allowed-ipsip 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, який перезаписує резолвер адресою, доступною лише всередині тунелю, провалить кожен запит у момент падіння тунелю, і це виглядає так, ніби тунель ламає інтернет.
| Symptom | Layer to inspect |
|---|---|
| Tunnel address pings, nothing else does | Client route, then gateway forwarding |
| Public IP pings, hostnames fail | Resolver selection and reachability |
| Handshake completes, no reply ever | FORWARD policy or missing NAT on the server |
| Small requests work, large transfers stall | MTU and TCP MSS clamping |
Порядок, що дає докази
Спершу виконайте перевірку на боці клієнта, бо це одна команда і вона усуває половину можливостей. Потім підтвердьте, чи сервер узагалі призначений бути виходом в інтернет; шлюз, збудований для приватного доступу, не зламаний, коли публічні призначення недоступні.
На сервері стежте за інтерфейсом, поки надсилаєте пінг з клієнта: tcpdump -ni wg0 icmp має показати запит, а tcpdump -ni eth0 icmp — що він виходить, перекладений чи ні. Якщо він з'являється на першому і ніколи на другому, зупинка локальна на сервері. Якщо він виходить, а відповідь не повертається, проблема вище, і це вже інша розмова.
Насамкінець зробіть так, щоб виправлення пережило перезавантаження. Пересилання належить до файлу sysctl, правила міжмережевого екрана — до служби, яка їх завантажує, а маршрути клієнта — до конфігурації, яка піднімає інтерфейс, а не до оболонки, яку ви забудете. Перепідключіться, повторіть ті самі два тести й переконайтеся, що лічильники рухаються.