Чому маршрути з однаковою вартістю роблять збої VPN важко помітними
Коли кілька тунелів поділяють одну вартість, кожен потік може обрати інший. Успішний ping нічого не каже про шлях, який ваша програма насправді використовує.
Користувач повідомляє, що внутрішня програма працює з однієї машини і не працює з іншої, а ping, запущений зі шлюзу, успішний в обох випадках. За кількох тунелів з однаковою вартістю це не суперечність. Кожен потік розміщується на своєму наступному хопі, тому ваша перевірка й сеанс користувача можуть просто використовувати різні шляхи. Розбір нижче відтворює цей вибір до будь-яких змін.
Один ping, кілька можливих шляхів
Коли маршрут має більше ніж один наступний хоп з однаковою вартістю, маршрутизатор має вибрати один на кожен пакет. Більшість реалізацій хешують поля пакета, зазвичай адреси джерела й призначення разом із протоколом і портами, щоб відповіді залишалися на тому самому шляху. Різні програми, навіть різні з’єднання однієї програми, дають різні хеші.
Саме тому діагностика зі шлюзу доводить так мало. Власна перевірка шлюзу має свої адреси й порти, а отже й свій хеш. Вона може потрапити на справний тунель, тоді як користувач продовжує потрапляти на зламаний.
Як платформа вибирає наступний хоп
Відтворіть вибір замість того, щоб його вгадувати. Запитайте ядро, який маршрут воно використало б для тих самих джерела й призначення, що й збійний сеанс. Цей пошук включає поля, які звичайний пошук за призначенням ігнорує. Запустіть його також із робочого клієнта і порівняйте дві відповіді:
ip route get 10.20.5.7 from 10.20.0.14
Новіші випуски iproute2 приймають також протокол і порт призначення, що важливо, коли хеш включає їх. Порівняйте цей вивід із тим самим пошуком із робочого клієнта, і різниця буде доказом, якого вам бракувало.
| Observation | Likely cause | First check |
|---|---|---|
| Ping works, application fails | A different flow hash selects another tunnel | Per-flow lookup from the client's address |
| Some users fail, others do not | One tunnel lacks a prefix or selector | Compare both tunnels' installed routes |
| Fails only at larger sizes | Tunnels have different effective MTU | Probe the same size over each path |
| Fails after a reconnect | Stateful asymmetry between paths | Session state on both gateways |
Ідіть за збійним потоком, а не за таблицею маршрутів
Таблиця маршрутів перелічує обидва тунелі й за визначенням виглядає правильною. Питання в тому, що кожен тунель робить із пакетом після вибору. Перевірте, що обидва несуть однакові захищені префікси, однаковий дозвіл на пересилання й зворотний шлях, що досягає того самого клієнта.
Зверніть увагу на пристрої зі станом посередині. Якщо запит виходить через один тунель, а відповідь повертається через інший, міжмережевий екран або NAT, який ніколи не бачив початковий потік, відкине його. Обидва тунелі правильно пересилають трафік, і з’єднання все одно збоїть.
Перевірте також MTU на кожному шляху. Шлях із додатковою інкапсуляцією зменшує корисний розмір, і передавання, яке проходить через один тунель, застрягає на іншому рівно на тому розмірі, де ламається менший.
Порівнюйте по одному шляху за раз
Там, де архітектура допускає обслуговування, виведіть один тунель з експлуатації та повторіть завдання користувача. Якщо збій зник, проблема належить видаленому шляху, і наступний крок — порівняти його конфігурацію із сусідньою, а не знову вивчати таблицю маршрутизації.
Порівнюйте реальну програму, а не повторні ping. Запишіть, чи збій іде за певним наступним хопом, розміром пакета або переходом після перепідключення, бо ці три закономірності вказують на різні виправлення.
Насамкінець запишіть, чому шляхи вважаються еквівалентними і як збій має виводити один із них з експлуатації. Багатошляховість безпечна лише тоді, коли шляхи справді взаємозамінні, і це проєктне твердження, яке варто перевірити, а не припускати.