WireGuard працює лише після того, як сервер надішле: знання кінцевої точки
Успіх, що залежить від напрямку, зазвичай означає, що одна сторона так і не дізналася адресу іншої. Порівняйте кінцеві точки, потім перевірте, чи не завершився термін дії таблиці трансляції.
Тунель ніби працює лише після того, як сервер першим щось надішле. Запустіть із клієнта — нічого не відбувається, зачекайте кілька секунд, спробуйте знову — і виходить. Звичайний діагноз — зламаний NAT, і звичайний діагноз хибний. Змінилося те, що одна сторона дізналася, де живе інша.
Знання кінцевої точки, а не досяжність
Сторона WireGuard не почне рукостискання, доки не дізнається, куди його надсилати. Конфігурація задає це як кінцеву точку з адреси й порту, а робочий стан відстежує кінцеву точку, у яку він вірить зараз.
wg show друкує обидві сторони цієї картини, і сторона без кінцевої точки у виводі не може нічого почати, хоч би якими правильними були її відкритий ключ і дозволені префікси. Порівняйте погляд клієнта з поглядом сервера, перш ніж змінювати будь-яке правило, бо вони часто не погоджуються щодо того, хто що знає.
Як сторона дізнається кінцеву точку
WireGuard навмисно мовчазний. Коли правильно автентифікований пакет надходить з адреси, якої сторона не очікувала, реалізація оновлює кінцеву точку цієї сторони на нове джерело, і саме так працює роумінг на ноутбуці, що змінює мережі. Така поведінка пояснює залежність від напрямку: якщо сервер надсилає першим і його пакет доходить до клієнта, клієнт дізнається поточну адресу сервера і може відповісти. До того часу йому нікуди надсилати. Механізм — це автентифікований роумінг, а не скорочення «довіра при першому використанні», бо пакет мав бути дійсним до того, як кінцева точка змістилася.
Документація інструментів для wg описує те оновлення, і її варто прочитати один раз, якщо ви збираєтеся проєктувати навколо цього.
Трансляція зі станом додає свій напрямок
Коли UDP проходить через транслювальний шлюз, шлюз створює стан для першого побаченого пакета. RFC 4787 описує цю поведінку та тайм-аути, які зрештою видаляють відображення. Неактивне відображення спливає, і вхідний пакет із далекої сторони тоді відкидається шлюзом ще до того, як дійде до хоста. Тунель, який працював усю ранок, перестає відповідати після обіду саме з цієї причини.
Це другий і незалежний механізм, що дає той самий напрямний симптом. І знання кінцевої точки, і стан трансляції мають бути правильними, і виправлення одного не виправляє іншого.
Налаштуйте той напрямок, який справді потрібен
Для клієнта, який має починати з'єднання, помістіть кінцеву точку сервера в розділ сторін клієнта і залиште її там. Покладатися на те, що сервер надішле першим, — це покладатися на випадковість у порядку трафіку, яка зміниться в тихій мережі. Конфігурація має заявляти передбачуваний напрямок, а не виявляти його.
Для сторони за трансляцією, яка має залишатися досяжною, увімкніть постійний keepalive на цій стороні. Keepalive кожні 25 секунд — звичайне початкове значення, і його мета — тримати відображення відкритим, а не перевіряти тунель. Оберіть одну сторону, яка його нестиме, бо ввімкнення на обох сторонах подвоює трафік і шум у журналах, не покращуючи результат.
Порівняйте стан до і після тригера
Зафіксуйте два подання в момент відмови, а потім ще раз після того, як сервер надішле. Перша команда показує кінцеві точки й вік рукостискання. Друга показує, чи є запис трансляції для порту. Запис показує, який напрямок справді перетнув дріт, а перевірка маршруту підтверджує, що клієнт не надсилає цей трафік зовсім в інше місце.
wg show conntrack -L -p udp 2>/dev/null | grep 51820 tcpdump -ni any -c 20 'udp port 51820' ip route get 198.51.100.7
Запишіть стовпець кінцевої точки й запис трансляції разом. Сторона без кінцевої точки й шлюз без відображення — дві різні несправності. Лише одну з них виправляє keepalive.