Чи справді трафік іде через VPN? Як це перевірити
Пошук маршруту, перший стрибок, перехоплення на фізичному адаптері та перевірка адреси ззовні відповідають на різні частини питання.
Дві несправності виглядають однаково зі значка в системному лотку: трафік, що входить у тунель, і трафік, що тихо його обходить. Клієнт в обох випадках показує 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 see | What it means | Next step |
|---|---|---|
| The route picks tun0 but the capture shows cleartext to 10.20.5.7 | Something bypassed the table: a bound app, a policy route or a session older than the tunnel | Reset the flow, check the app bind, check the ip rule list |
| The route picks eth0 for an internal name | The name resolves to a public address, or the route was never installed | Compare the resolved address with the routes the server pushes |
| The capture shows DNS to the LAN resolver | Resolver leak: data is tunneled, lookups are not | Point the resolver inside, or push it from the server |
| All four checks agree and one app still fails | Path selection is fine; suspect MTU, a per-app proxy or the far end | Test the same destination from a known-good client |
Робочий порядок: збережіть таблицю маршрутизації до і після підключення, простежте одне внутрішнє і одне публічне ім'я, перехопіть DNS на фізичному адаптері, поверніть адресу виходу з оболонки для конкретного застосунку, потім прочитайте сервер щодо обсягу. Якщо перші чотири збігаються, тунель несе те, що ви думаєте, і залишкова проблема вище. Якщо дві з них розходяться, пара, що розходиться, і є несправністю, а не значок.