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

Почніть з маршруту, яким піде пакет

Таблиця маршрутизації і є рішенням, тому запитайте її про одну адресу, а не читайте всю і вгадуйте. У Linux ip route get називає інтерфейс і адресу джерела, які вибрало ядро:

ip route get 203.0.113.10
ip route get 10.20.5.7

У Windows Find-NetRoute -RemoteIPAddress 203.0.113.10 корисніший за route print -4 з тієї ж причини: він повідомляє про переможний маршрут, а не про всі наявні. Усе ж прочитайте таблицю один раз заради її рядка 0.0.0.0. Пара /1 там означає, що клієнт повного тунелю переписав маршрут за замовчуванням: опція redirect-gateway def1 OpenVPN встановлює 0.0.0.0/1 і 128.0.0.0/1 через тунель, і це перемагає наявний 0.0.0.0/0 за найдовшим збігом префікса, не видаляючи фізичний маршрут за замовчуванням. Тому два маршрути за замовчуванням можуть співіснувати, а все одно йде в тунель.

Дві деталі роблять таблицю брехливою. По-перше, дивіться на префікс, що збігся, а не на кількість маршрутів за замовчуванням, бо переможця визначає метрика інтерфейсу або пара /1. По-друге, наявне з'єднання зберігає шлях, з яким було встановлене; після підйому тунелю відкрита сесія може продовжувати користуватися старим маршрутом, доки її не скинуть, і саме тому повторне підключення ніби виправляє проблему маршрутизації. Працюючий клієнт — ps ax | grep openvpn — доводить лише те, що процес запустився.

Простежте одне внутрішнє і одне публічне ім'я

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

traceroute intranet.corp.example
traceroute 1.1.1.1

Однаковий перший стрибок для обох означає, що внутрішнє ім'я ніколи не входило в тунель і несправність вище, зазвичай це ім'я, що розв'язується в публічну адресу, або маршрут, який так і не було встановлено. Якщо внутрішній трафік виходить через 10.8.0.1, а публічний через 192.168.1.1, розділений тунель робить саме те, для чого його налаштували. Слід, що досягає шлюзу VPN і потім повертає лише тайм-аути, зазвичай означає проблему зворотного шляху або брандмауера сервера, а не відсутній маршрут пересилання.

Відфільтрований ICMP робить цю перевірку брехливою: зірочки на обох слідах виглядають як мертвий тунель і зазвичай це брандмауер. Перевірте TCP-порт там, де можете — traceroute -T -p 443 у Linux — і пам'ятайте, що слід не говорить, який розв'язувач відповів: ім'я може розв'язатися локально і все ж бути доступним через тунель.

Перехоплюйте на фізичному адаптері, а не на тунелі

Фізичне з'єднання — єдине місце, яке показує, що мережа справді бачить. Коли тунель піднято, сесія до офісу має виглядати як зашифроване навантаження, адресоване серверу VPN, а не як з'єднання з 10.20.5.7:

sudo tcpdump -ni eth0 udp port 53
sudo tcpdump -ni eth0 host 10.20.0.5

Перший фільтр ловить розв'язання імен, що виходить локально, і це найпоширеніший і найтихіший витік — сторінка все одно завантажується, розв'язувач просто побачив запит. Другий ловить звичайний трафік до внутрішньої адреси, яка має існувати лише всередині тунелю. У Windows pktmon робить ту саму роботу без драйвера: pktmon filter add -p 53, потім pktmon start --capture --pkt-size 128, потім pktmon stop і pktmon format pktmon.etl -o capture.txt. Ці прапорці трохи різняться між збірками Windows, тому перевірте pktmon filter add /?, перш ніж довіряти синтаксису.

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

Запитайте зовнішній сервіс, а потім запитайте ще раз для кожного застосунку

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

sudo curl --interface tun0 https://example.net/ip
sudo curl --interface eth0 https://example.net/ip

Різні відповіді дають доказ обох шляхів і спосіб перевірити конкретний застосунок: прив'яжіть його або запустіть у мережевому просторі імен з одним маршрутом і подивіться, яку адресу запише дальній кінець. Однакові відповіді — це цікава несправність: або прив'язка не подіяла, або щось між хостом і дальнім кінцем переписує адресу джерела до прибуття. У Windows curl --interface вимагає адресу адаптера, а не його ім'я.

Браузер, що повідомляє адресу VPN, доводить браузер. Поштовий клієнт, менеджер пакетів, агент резервного копіювання або другий профіль браузера можуть кожен іти своїм шляхом, особливо коли налаштування проксі або маршрут розділеного тунелю охоплює один із них. Зміна адреси сама по собі не є доказом витоку: балансувальник може відповісти інакше залежно від побаченого виходу, тому порівнюйте записану адресу джерела, а не сторінку.

Використайте подання сервера, щоб підтвердити партнера

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

Тут чатують дві пастки. Маскований тунель змушує кожен потік виглядати так, ніби він приходить від шлюзу, тож журнали й облік за клієнтами зливаються в одну адресу. А клієнт розглядається як локальний хост, тому питання, чи хтось копіює файли через VPN, вирішує трафік спільного доступу до файлів на сервері або аудит хоста на сервері — спостереження за тунелем дає кінцеві точки й обсяг, а не імена файлів.

Відрізніть проєктне рішення від витоку

Не все за межами тунелю — витік. Трафік локального зв'язку й широкомовний залишається локальним за проєктом, принтер, знайдений через multicast, продовжує оголошувати себе в LAN, а DHCP мусить виходити локально. Застосунок, прив'язаний до конкретного інтерфейсу, навмисно обходить таблицю маршрутизації, і це змінює лише правило брандмауера, простір імен або політичний маршрут.

IPv6 заслуговує окремого рядка в контрольному списку. Тунель, що несе лише IPv4, залишає двостековому хосту другий придатний шлях, і двостековий адресат віддасть йому перевагу — включно з DNS, якщо розв'язувач доступний через IPv6. Вимкніть IPv6 на адаптері або підтвердьте, що тунель його несе, перш ніж вважати результат IPv4 повним.

Коли перевірки розходяться, розходження зазвичай називає несправність:

What you seeWhat it meansNext step
The route picks tun0 but the capture shows cleartext to 10.20.5.7Something bypassed the table: a bound app, a policy route or a session older than the tunnelReset the flow, check the app bind, check the ip rule list
The route picks eth0 for an internal nameThe name resolves to a public address, or the route was never installedCompare the resolved address with the routes the server pushes
The capture shows DNS to the LAN resolverResolver leak: data is tunneled, lookups are notPoint the resolver inside, or push it from the server
All four checks agree and one app still failsPath selection is fine; suspect MTU, a per-app proxy or the far endTest the same destination from a known-good client

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

Схожі статті