Симптоми дотримуються однієї схеми: хост працює, потім підключається до VPN як клієнт, і тепер LAN-клієнти до нього доходять, а його відповіді зникають. Перехоплення на хості показує, що відповіді виходять через пристрій тунелю, а не через LAN-інтерфейс. Сам тунель не зламаний, і виправлення — це маршрут, а не перепідключення. Виконайте чотири перевірки нижче по порядку й зупиніться на першій невдалій.

Відповідь — це новий пакет, а не розворот шляху

Корисно відмовитися від думки, що відповідь повертається тим самим шляхом, яким пішов запит. Маршрутизація вирішується для кожного пакета й кожного напрямку на хості-відправнику. Запит, що надійшов з 10.64.0.23 усередині тунелю, не створює зворотного шляху; коли хост відповідає, ця відповідь зіставляється з таблицею як новий пакет і виходить тим маршрутом, що перемагає.

Тому клієнт із повним тунелем на машині, яка також обслуговує LAN, дає таку заплутану відмову. Клієнт встановлює маршрут за замовчуванням або два половинчасті маршрути за замовчуванням, які віддають перевагу деякі клієнти, і відповідь LAN-клієнту тепер збігається з тунелем. Вона йде до провайдера, який не має причин її пересилати, а LAN-клієнт бачить тайм-аут, хоча хост працює й відповідає локально. Перехоплення робить це очевидним, а таблиця маршрутизації пояснює.

Тримайте в голові дві підмережі, читаючи решту. Одна — пул адрес VPN, звідки приходять віддалені клієнти, у цьому прикладі 10.64.0.0/24. Друга — LAN, який має далі працювати, 172.16.24.0/24 з маршрутизатором на 172.16.24.1. Помилка в тому, що трафік між ними вирішує маршрут за замовчуванням.

Доведіть це перехопленням і запитом

Перш ніж щось змінювати, підтвердьте, який пристрій використає відповідь. Запит швидший за перехоплення й відповідає рівно на те питання, на яке відповість ядро під час складання пакета.

ip route get 10.64.0.23 from 172.16.24.10
tcpdump -ni any -c 6 icmp

Читайте відповідь у двох частинах. Якщо вона називає dev tun0, хост інкапсулює відповідь і передасть її провайдеру, а LAN-клієнт її ніколи не побачить. Якщо вона називає dev eth0, але клієнт усе одно отримує тайм-аут, маршрут уже правильний і пакет відкидається пізніше, що є іншою проблемою з іншим виправленням.

Перехоплення на тому самому кроці знімає сумнів, який ping зняти не може. Ехо-відповідь, що доходить до LAN-клієнта, доводить, що якийсь шлях працює, а не який інтерфейс його ніс, тому робіть перехоплення на самому хості й дивіться, звідки виходять кадри. Принтер у тій самій підмережі далі відповідає, бо його прямий маршрут конкретніший за маршрут тунелю за замовчуванням. Проброшений порт відмовляє точно як будь-який інший потік, бо інтерфейс вибирає таблиця, а не з'єднання.

Встановіть найвужчий маршрут, що перекриває тунель

Вирішує довжина префікса, а не метрика, тому маршрут для пулу клієнтів через LAN-маршрутизатор перемагає будь-який маршрут за замовчуванням, який встановить VPN-клієнт. Хірургія метрики не потрібна, і маршрут за замовчуванням може залишитися рівно там, де його поставив клієнт.

ip route replace 10.64.0.0/24 via 172.16.24.1 dev eth0
ip route get 10.64.0.23 from 172.16.24.10

Використовуйте replace, а не add, бо клієнт, який перепідключиться, уже встановить свій запис, а другий add відмовляє з помилкою про наявний маршрут, що читається як проблема з правами. На хості Windows еквівалент — route add 10.64.0.0 mask 255.255.255.0 172.16.24.1 -p, де -p зберігає запис між перезавантаженнями, оскільки клієнт може перебудувати таблицю, коли тунель знову підніметься. На сучасному хості Windows підтримуваний еквівалент — New-NetRoute -DestinationPrefix 10.64.0.0/24 -NextHop 172.16.24.1 -InterfaceAlias Ethernet -PolicyStore PersistentStore, а стара команда route лишається як застаріла форма.

Одна деталь вирішує, чи це правильно, чи лише правдоподібно: наступний стрибок має бути маршрутизатором, який справді володіє шляхом назад до клієнтів. Спрямування маршруту на адресу, до якої сам доходиш через тунель, створює петлю, що проявляється як періодичні втрати, а не як чиста відмова. Підтвердьте, що наступний стрибок у LAN-підмережі, перш ніж фіксувати рядок.

Збережіть відповідь після перепідключення

Маршрут, доданий вручну, живе в найкращому разі до наступного перепідключення. Якщо пул клієнтів динамічний, закріпіть його в конфігурації сервера, щоб префікс, який ви маршрутизували, залишився префіксом, який отримують клієнти; інакше запис указує на порожній діапазон, і симптом повертається через тижні без очевидної причини. Записати маршрут у власний up-скрипт клієнта — інший надійний варіант, бо він виконується після того, як клієнт перезаписав таблицю.

Міжмережевий екран з відстеженням станів усе одно може подолати правильний маршрут. Якщо перехоплення тепер показує, що відповідь виходить через eth0, а клієнт усе одно отримує тайм-аут, перевірте, чи не відкидає хост пакет до надсилання. Строга фільтрація зворотного шляху і net.ipv4.conf.all.rp_filter, встановлений у 1, відкидають пакети, джерело яких не було б маршрутизовано назад через той інтерфейс, через який вони прийшли, і це саме той асиметричний випадок, який ви щойно створили й потім виправили, а стан conntrack розповідає ту саму історію для проброшених портів.

Остання перевірка — та, яку люди пропускають: повторіть запит після того, як тунель опускався й знову піднімався. Чотири значення мають збігтися з тим, що ви записали: призначення, наступний стрибок, пристрій і вибране джерело. Якщо щось із цього змістилося, клієнт перезаписав таблицю, і виправлення належить його хукам, а не історії оболонки.

Схожі статті