«Чи ввімкнено VPN?» — насправді три питання в одному реченні. Яке з них потрібне вашому коду — це перше рішення, і саме його більшість реалізацій пропускає. Чи є тунель на цьому пристрої, чи виходить трафік до цього пункту призначення через нього, чи далекий бік відповідає тією ідентичністю, яку ви очікуєте. Виберіть властивість, потім сигнал, який її вимірює, і наприкінці запишіть у журналі, який саме ви виміряли.

Три властивості, три сигнали

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

PropertySignal that answers itWhat it still leaves open
ExistenceThe platform's own connection state: RAS on Windows, NetworkManager on D-Bus on Linux, scutil on macOSTunnels of a type the platform does not manage, which includes most third-party clients
PathA route lookup for the one destination, or a scoped proxy or interface key that names the tunnelWhether the far end is the peer you trust
IdentityAn authenticated response from the far end, or a source-address policy applied on the serverWhich local interface carried the packets

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

Існування: власний стан платформи

Windows відповідає на це для рідних профілів через Remote Access Service API. RasEnumConnections перелічує, що підключено, RasGetConnectStatus повідомляє стан одного запису, а RasGetLinkStatistics додає швидкість, лічильники байтів і вік з’єднання. Обмеження і є суттю: OpenVPN, WireGuard і клієнти виробників ніколи не реєструють з’єднання RAS, тому справний тунель такого типу показує порожній список, і наївний код повідомляє, що він вимкнений.

Робочі столи Linux надають ту саму властивість через NetworkManager на D-Bus, де PropertiesChanged на об’єкті VPN-з’єднання перетворює перевірку на подію, а властивість State повідомляє, коли з’єднання досягає стану підключено. З оболонки nmcli connection show --active читає ту саму інформацію, і саме це потрібно під час налагодження. macOS тримає цей список у каркасі System Configuration, а scutil — його подання з командного рядка. Усі три описують з’єднання, яким керує платформа, і всі три мовчать про тунель, яким вона не керує.

Шлях: куди насправді йде пакет

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

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

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

Коли важливий саме пункт призначення, питайте таблицю маршрутизації, а не список адаптерів. Евристики шлюзу за замовчуванням ламаються на машинах із кількома мережами й на тунелях, які встановлюють власний шлюз.

Ідентичність: перевірте далекий бік

Цикл, який кожні кілька секунд надсилає ICMP-відлуння на далекий бік, — найдешевша перевірка такого роду, і вона відмовляє в корисному напрямку. Спрямуйте його на адресу, що існує лише всередині приватної мережі, бо публічна відповідає через будь-який робочий висхідний канал і нічого не доводить. Там, де ICMP фільтрується, коротке TCP-з’єднання з портом служби робить ту саму роботу.

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

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

Записуйте категорію, а не вердикт

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

Зведення їх в одне «VPN упав» надсилає звіт команді, яка не може це виправити. Категорія — корисний результат; вердикт — це те, що робить його хибним.

Схожі статті