Root — не те, що дозволяє VPN-застосунку на Android передавати трафік, блокувати витоки чи переживати перезавантаження. Люди зводять усе це до фрази «застосунок має дозвіл VPN», а вона приховує три окремі механізми: згоду користувача, пакетний інтерфейс, який створює система, і політику блокування платформи, яку не застосунку визначати. Оцінювати дизайн VPN на Android означає питати, на що з цих трьох насправді спирається твердження, бо кожен має іншого власника й інший режим відмови.

Згода надходить через системну активність

VpnService.prepare() нічого не надає. Він повертає intent до системної активності згоди, коли згоди немає, і застосунок відкриває цей діалог, щоб користувач схвалив сервіс. Запуск власного процесу застосунку, додавання дозволу до маніфесту чи показ власного екрана «увімкнути VPN» не створюють згоди.

Згода також має межі. Вона належить пакету в профілі користувача, тому особиста копія й робоча копія — різні рішення, і власник пристрою може підготувати керований профіль інакше, ніж особистий. Якщо діалог ніколи не з'являється, а prepare() повертає null, згода для цього пакета в цьому профілі вже є; це не доказ надійності застосунку, лише те, що дозвіл на місці.

Інтерфейс — це запит, який виконує система

Після згоди застосунок описує бажане за допомогою VpnService.Builder: адреси, маршрути, сервери DNS, MTU і, де це підтримується, застосунки для включення чи виключення. establish() просить систему створити інтерфейс тунелю й спрямувати туди відповідний трафік. Рішення про маршрутизацію належить системі; застосунок отримує файловий дескриптор і далі має зробити з пакетами щось корисне.

What you observeWho actually owns it
VPN consent dialogThe system, triggered by prepare()
Routes, DNS and app listsThe app requests them; the system applies them
One active VPN per profileThe platform; a new service replaces the old one
Always-on and block-without-VPNDevice policy enforced by the platform

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

Сокет тунелю має вирватися з власного тунелю

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

adb shell dumpsys connectivity | grep -i -A5 vpn
adb shell settings get global always_on_vpn_app
adb shell settings get global always_on_vpn_lockdown

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

Блокування може належати платформі

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

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

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

Чотири питання для огляду дизайну

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

Четверте питання — те, на яке модель дозволів відповісти не може. Згода й інтерфейс TUN доводять, що застосунок може приймати трафік, а не те, що він його шифрує, автентифікує партнера чи чисто відновлюється. Це властивості реалізації, і саме там чесний огляд проводить свій час.

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

Схожі статті