Коротка відповідь
VPN-застосунок на Android не забезпечує повного контролю над вихідним трафіком пристрою. Він є мережевою політикою, яку операційна система застосовує до ідентифікаторів застосунків, і ця політика за задумом не поширюється на системні процеси, на роздачу інтернету та на низку службових зʼєднань.
Перемикач «Блокувати підключення не через VPN» — те, що зазвичай називають kill switch або кіл-світч, — блокує саме застосунки. У вихідному коді мережевої підсистеми Android сокети, що належать ідентифікаторам нижче за FIRST_APPLICATION_UID — тобто системним компонентам, зокрема system_server, radio та network_stack, — позначаються як PERMISSION_SYSTEM і взагалі не проходять перевірку доступу до мережі. Їм дозволено будь-яку мережу, включно з фізичним інтерфейсом Wi-Fi, незалежно від стану тунелю.
Це не помилка і не недогляд. Без такого винятку операційна система не змогла б виконувати частину власних функцій. Але наслідок для користувача прямий: жодне налаштування в телефоні не переведе весь вихідний трафік у тунель, тому що механізм примусу застосовується не до пристрою, а до застосунків.
Єдина конфігурація, у якій увесь трафік телефона гарантовано проходить через тунель, виглядає так: стільниковий модуль вимкнено, підключення тільки через Wi-Fi, а тунель піднято на маршрутизаторі. Тоді рішення про маршрутизацію ухвалює не телефон.
Як влаштоване примусове спрямування трафіку в Android
Кожен сокет в Android має позначку SO_MARK (fwmark), яка вказує ядру, до якої мережі він належить. Коли VPN піднімається, таблиці маршрутизації та правила netd для окремих застосунків переписуються так, що для заблокованих ідентифікаторів єдиною доступною мережею стає тунель. Якщо застосунок намагається привʼязати сокет безпосередньо до фізичного інтерфейсу Wi-Fi, виклик проходить через fwmark-сервер, той викликає checkUserNetworkAccess(), бачить заблокований ідентифікатор і повертає EPERM.
Для застосунків цей механізм працює. Виняток описано в system/netd/server/NetworkController.cpp двома рядками, які й визначають усе подальше:
return uid < FIRST_APPLICATION_UID ? PERMISSION_SYSTEM : PERMISSION_NONE;
if ((userPermission & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) {
return 0; // дозволяє доступ до БУДЬ-ЯКОЇ мережі, включно з фізичним Wi-Fi
}
Системний компонент, який надсилає пакет, не перевіряється на предмет того, чи активний зараз тунель і чи заблоковано мережевий доступ поза ним. Перевірка просто не виконується.
Із цього випливають дві речі. Перша: будь-який трафік, що фізично надсилається системним процесом, залишає пристрій повз тунель. Друга: якщо застосунок здатний спонукати системний процес надіслати пакет від свого імені, тунель обходиться теж — і саме цим виявився публічно продемонстрований у квітні 2026 року обхід, описаний нижче.
Що офіційно виведено з-під тунелю
Найточніше формулювання належить інженерові Google у відповіді на звернення до трекера помилок Android. Перевірка наявності інтернет-зʼєднання, за його словами, далеко не єдине, що виведено з-під VPN: привілейовані застосунки також можуть обходити тунель, і для багатьох із них це необхідно для роботи; як приклад названо IWLAN та трафік роздачі інтернету.
Розглянемо ці категорії.
Перевірка наявності інтернет-зʼєднання. Android виконує її під час кожного підключення до мережі Wi-Fi, щоб виявити captive-портал. Це було публічно задокументовано у 2022 році: перевірки виходять повз тунель навіть за увімкненого «Блокувати підключення не через VPN», і разом із ними назовні йдуть DNS-запити, HTTP- і HTTPS-трафік та, ймовірно, NTP. Google закрив звернення з формулюванням про очікувану поведінку. У тому ж зверненні окремо наголошувалося, що назва самого перемикача та документація до нього вводять користувача в оману, бо створюють враження, ніби пристрій не надсилає нічого поза тунелем.
Тут GrapheneOS дає реальну перевагу над заводською Android: перевірки підключення можна перемкнути на сервер GrapheneOS або вимкнути повністю в розділі «Network & internet». Це незалежно перевірено: з вимкненими перевірками описаного витоку не спостерігається.
IWLAN, тобто дзвінки через Wi-Fi. Служби VoLTE, VoNR, VoWi-Fi, RCS, MMS, SMS поверх LTE та візуальна голосова пошта реалізовані переважно самою операційною системою поверх TCP/IP, а не стільниковим рівнем. Це означає власні зʼєднання операційної системи до серверів оператора через підсистему IMS і домени 3gppnetwork.org. Ці зʼєднання належать системним ідентифікаторам, і тунель застосунку їх не охоплює. GrapheneOS змінює конфігурацію оператора так, щоб перемикачі вимкнення VoLTE, VoNR і VoWi-Fi були доступні завжди — але це вимкнення служби, а не її переведення в тунель.
Роздача інтернету. Винесено в окремий розділ нижче.
Привілейовані застосунки загалом. Формулювання Google не обмежене переліком. Це категорія, а не список, і вона може змінюватися між версіями.
Роздача інтернету ніколи не потрапляє в тунель
Це найчастіша практична несподіванка. Телефон із піднятим тунелем роздає Wi-Fi або USB, підключений ноутбук перевіряє свою зовнішню адресу — і бачить адресу оператора, а не вихідного вузла VPN. Коли тунель на телефоні розривають, браузер телефона перестає відкривати сторінки, а ноутбук продовжує працювати як ні в чому не бувало.
Причина не в обмеженні ядра Linux, як іноді припускають, а в архітектурі мережевої підсистеми AOSP. VPN в Android діє в межах профілю користувача: тунель належить профілю і поширюється на застосунки цього профілю. Підключений ноутбук, планшет чи телевізор не належать до жодного профілю на телефоні, тому жоден тунель телефона їх не охоплює.
Пересилання трафіку роздачі виконують системні компоненти, а вони, як показано вище, позначаються як PERMISSION_SYSTEM і перевірку доступу до мережі не проходять. Саме тому роздачу інтернету й названо в переліку винятків поряд із IWLAN: вона виведена з-під тунелю на тому самому архітектурному рівні.
Механізму, який спрямував би трафік роздачі в тунель профілю, в AOSP немає. Це не приховане десь налаштування і не властивість конкретної збірки: інтерфейс VPN-застосунків такої можливості не передбачає взагалі, тому й жодна операційна система на базі AOSP не може надати її засобами цього інтерфейсу. Реалізація потребувала б власного тунелю всередині операційної системи, здатного видавати кожному підключеному пристрою окремий маршрут.
Обхідні засоби існують, але потребують root-доступу: вони вставляють власні правила маршрутизації у проміжок між пріоритетами локальної мережі та роздачі інтернету. Отримання root-доступу на Pixel вимагає розблокування завантажувача, що вимикає перевірене завантаження. Ми не застосовуємо це на пристроях і не рекомендуємо.
Окремо варто знати ще одне: сам факт роздачі помітний операторові навіть тоді, коли підключений пристрій піднімає власний тунель, — зокрема через відмінності у значенні TTL у пакетах, що пройшли через додатковий вузол.
Витоки DNS
Розвʼязання доменних імен є окремою підсистемою зі своєю історією проблем.
Незалежні дослідники задокументували у 2024 році кілька сценаріїв, у яких Android надсилає DNS-запити повз тунель: коли VPN активний, але сервер DNS у ньому не налаштовано, і протягом короткого проміжку, поки застосунок переналаштовує тунель, аварійно завершується або примусово зупиняється. Витоки виникають під час прямих викликів функції getaddrinfo і відтворювалися саме на застосунку WireGuard, який вважають еталонною реалізацією VPN для Android. Ключова деталь: це відбувається незалежно від стану «Постійна мережа VPN» і «Блокувати підключення не через VPN».
GrapheneOS частину цих сценаріїв закриває. Проєкт прямо описує, що Android дозволяє запитам системного розвʼязувача просочуватися до серверів DNS мережі через стан гонитви, коли VPN-застосунок припиняє роботу, і так само дозволяє зʼєднанням до серверів DNS самого тунелю відбуватися поза тунелем; обидва випадки в GrapheneOS усунено розширенням блокування на цю частину системного розвʼязувача.
Є й конфігураційна пастка. Private DNS має пріоритет над серверами DNS, які надає тунель, оскільки з погляду системи це сервери мережі. Тому GrapheneOS рекомендує не тримати Private DNS налаштованим одночасно з VPN, а для вторинних профілів наполягає на повному вимкненні Private DNS до перероблення цієї підсистеми. Комбінація, яку користувач використовує задля приватності, у цьому випадку працює проти нього.
Помилки реалізації зʼявляються регулярно
Крім категорій, виведених з-під тунелю навмисно, існують помилки. Свіжий і показовий приклад опубліковано 30 квітня 2026 року.
В Android 16 зʼявився механізм коректного завершення зʼєднань QUIC: застосунок може заздалегідь зареєструвати кадр CONNECTION_CLOSE, який операційна система надішле від його імені, коли сокет буде закрито. Метод registerQuicConnectionClosePayload у ConnectivityManager приймає довільний масив байтів і не перевіряє ані дозволів того, хто викликає, ані вмісту переданих даних, ані того, чи заблоковано виклику мережевий доступ поза тунелем. Надсилає дані system_server, який, як показано вище, від перевірок звільнений.
Результат: звичайний застосунок, що має лише два дозволи, які видаються автоматично, надсилає довільні байти на довільну адресу повз активний тунель і розкриває справжню адресу пристрою. Перевірено на Pixel 8 з Android 16 та ввімкненими «Постійна мережа VPN» і «Блокувати підключення не через VPN». Команда безпеки Android закрила звіт із позначкою «Won’t Fix (Infeasible)», а після апеляції рішення не змінила. GrapheneOS натомість виправив це у власній кодовій базі.
Це не поодинокий випадок. GrapheneOS перелічує на сторінці можливостей ще кілька класів обходу, які виправив самостійно: надсилання багатоадресних пакетів безпосередньо або через системні виклики керування групами багатоадресної розсилки, що дозволяло застосункам обходити тунель незалежно від того, піднятий він чи ні; можливість надіслати багатоадресні пакети через тунель, що належить іншому профілю; діру у фільтрації на базі eBPF, яка дозволяла обійти тунель, вказавши конкретний інтерфейс окремим системним викликом.
І найважливіше в цьому переліку — власна оцінка проєкту. GrapheneOS зазначає, що пошук і усунення всіх форм витоків VPN є одним із пріоритетів на цей момент і що функція наразі не вважається завершеною через додаткові виявлені проблеми. Це чесна позиція команди, яка зробила в цій області більше за будь-кого іншого, і саме тому її варто читати буквально.
Окремо про застосунок WireGuard на Pixel
Тепер про конкретний сценарій із запитання.
Офіційний застосунок WireGuard для Android використовує реалізацію в ядрі, якщо вона доступна, і повертається до реалізації у просторі користувача, якщо ні. Доступ до модуля ядра потребує root. На Pixel із GrapheneOS root відсутній, тому застосунок завжди працює у просторі користувача — тобто через реалізацію мовою Go поверх того самого механізму VpnService, з усіма описаними вище обмеженнями.
Далі йде специфічна для GrapheneOS деталь. Проєкт рекомендує дуже короткий перелік VPN-застосунків і зазначає, що апаратне маркування памʼяті виявляє некоректні звернення до памʼяті саме в офіційному застосунку WireGuard — на відміну від іншого застосунку з цього переліку, який перевірено на GrapheneOS з увімкненим маркуванням памʼяті. Окремо GrapheneOS повідомляв, що користувачі неодноразово знаходили помилки роботи з памʼяттю в застосунках на базі WireGuard під Android, і припускав, що більшість із них походить від середовища виконання Go.
Маркування памʼяті вмикається для встановлених користувачем застосунків на Pixel восьмого покоління і новіших. Тобто вмикання однієї з ключових функцій захисту GrapheneOS підвищує ймовірність аварійного завершення саме того застосунку, який тримає тунель. А аварійне завершення VPN-застосунку — це рівно та умова, за якої й зафіксовано описані вище витоки DNS.
Це не аргумент проти WireGuard як протоколу. Це аргумент проти конструкції, у якій цілісність усього мережевого захисту пристрою залежить від безперервної роботи одного застосунку у просторі користувача.
Чого VPN на телефоні не робить у принципі
Навіть якби всі перелічені витоки були усунені, залишається межа, яку VPN не перетинає за визначенням. Тунель працює на мережевому рівні. Все, що відбувається на радіорівні, лежить поза ним.
Зі вставленою SIM-карткою та увімкненим стільниковим модулем телефон реєструється в мережі оператора незалежно від стану тунелю. Оператор бачить IMSI, IMEI, час реєстрації та місцеперебування з точністю до соти. Жоден VPN на це не впливає. Ми розбирали суміжну тему в матеріалі про IMEI на Google Pixel.
Служби IMS додають до цього власні зʼєднання до серверів оператора, і, як зазначено вище, вони йдуть повз тунель.
Отже, VPN на телефоні відповідає на питання «хто бачить вміст і призначення мого IP-трафіку». Він не відповідає на питання «хто знає, що цей апарат зараз увімкнений і де він перебуває».
Конфігурація без витоків: Wi-Fi та маршрутизатор із тунелем
Конфігурація, яку ми рекомендуємо, коли завдання полягає саме в тому, щоб жоден пакет не залишив пристрій поза тунелем, складається з двох умов.
Перша: стільниковий звʼязок вимкнено. Режим польоту вимикає приймання і передавання стільникової радіочастини, після чого Wi-Fi вмикається окремо. Це усуває і реєстрацію в мережі оператора, і трафік IMS, і сам канал, яким витоки виходили б назовні. Якщо SIM-картка залишається в апараті та ввімкнено дзвінки через Wi-Fi, телефон продовжить реєструватися в оператора через Wi-Fi — тому дзвінки через Wi-Fi слід вимкнути або вийняти SIM-картку.
Друга: тунель піднято на маршрутизаторі. Маршрутизатор інкапсулює все, що виходить через його зовнішній інтерфейс. Тут немає ані політики на рівні ідентифікаторів застосунків, ані винятків для системних процесів, ані профілів користувача — тому що рішення про маршрутизацію ухвалює пристрій, який не має жодного з цих понять. Аварійне блокування реалізується правилом брандмауера, а не політикою операційної системи: якщо тунель не піднято, пакети просто не мають маршруту назовні.
Що ця конфігурація не робить, і про це слід сказати прямо:
- Вона не приховує телефон від того, хто керує маршрутизатором і точкою доступу. Точка доступу бачить MAC-адресу пристрою, запити DHCP та обсяг трафіку.
- Вона не зупиняє телеметрію застосунків. Тунель змінює маршрут, а не вміст.
- Перевірка наявності інтернет-зʼєднання нікуди не зникає — вона просто йде всередині тунелю, як і решта трафіку.
Тобто це розвʼязання задачі «нуль витоків повз тунель», а не задачі «анонімність».
Висновок
VPN-застосунок на Pixel із GrapheneOS не забезпечує повного контролю вихідного трафіку пристрою, тому що механізм примусу в Android застосовується до ідентифікаторів застосунків, а системні ідентифікатори з нього виключено на рівні мережевої підсистеми. Це не помилка конкретної збірки і не властивість конкретного застосунку.
Категорії, виведені з-під тунелю за задумом, підтверджено самим Google: перевірка наявності інтернет-зʼєднання, привілейовані застосунки, IWLAN і роздача інтернету. Роздача інтернету не потрапляє в тунель ніколи, і механізму, який це змінив би, в AOSP немає. Витоки DNS у сценаріях переналаштування та аварійного завершення задокументовано на офіційному застосунку WireGuard. Помилки реалізації, що дозволяють обійти тунель, зʼявляються регулярно, і сам GrapheneOS не вважає цю ділянку завершеною.
Конфігурація без витоків одна: стільниковий звʼязок вимкнено, підключення тільки через Wi-Fi, тунель піднято на маршрутизаторі. У ній телефон узагалі не визначає маршрут трафіку, тож і обійти його нема чому.
Застосунок VPN у телефоні при цьому не є марним. Він доречний як другий шар усередині маршрутизаторного тунелю та як засіб для тих випадків, коли контрольованого маршрутизатора немає під рукою. Він просто не є тим, чим його вважають.
Pixel 8, Pixel 9 та Pixel 10 із GrapheneOS. Ми підбираємо модель під вашу модель загроз, встановлюємо GrapheneOS, блокуємо завантажувач і передаємо пристрій із повним посібником з експлуатації. Деталі GrapheneOS →
Повʼязані: IMEI на Google Pixel · Pixel із GrapheneOS.
Джерела
Архітектура примусу та системний виняток
- «The Tiny UDP Cannon: An Android VPN Bypass», 30.04.2026 — розбір registerQuicConnectionClosePayload, вихідний код NetworkController.cpp і QuicConnectionCloser.java, хронологія розкриття. — lowlevel.fun
- Android Issue Tracker, обговорення 234170605 — відповідь інженера Google про те, що перевірки підключення далеко не єдине, що виведено з-під VPN, із прикладами IWLAN і роздачі інтернету. Перегляд трекера може вимагати входу до облікового запису Google. — issuetracker.google.com
- Android Developers, «VPN» — опис VpnService, режиму постійного підключення і поведінки за увімкненого блокування зʼєднань поза тунелем. — developer.android.com
Перевірка наявності інтернет-зʼєднання
- Android Issue Tracker, звернення 250529027 (витік) і 249990229 (документація).
Роздача інтернету
- Звіт 2145 «Hotspot traffic is not routed through (Wireguard) VPN» — відтворення поведінки та пояснення того, що VPN в Android діє в межах профілю користувача. — github.com
DNS
- Публічне розкриття сценаріїв витоку DNS в Android, 2024 — витоки відтворено на офіційному застосунку WireGuard.
- GrapheneOS, FAQ, розділи про DNS, Private DNS і підтримку VPN. — grapheneos.org
Заходи GrapheneOS і власна оцінка стану
- GrapheneOS, Features, розділ «Improved VPN leak blocking» — перелік закритих класів обходу та зауваження, що функція не вважається завершеною. — grapheneos.org
- GrapheneOS, FAQ, «What kind of VPN and Tor support is available?» — рекомендовані застосунки та зауваження про маркування памʼяті. — grapheneos.org
- GrapheneOS, допис від 28.09.2024 про помилки роботи з памʼяттю в застосунках на базі WireGuard. — grapheneos.social
Реалізація WireGuard для Android
- wireguard-android, опис проєкту: використовує реалізацію в ядрі за наявності, інакше — реалізацію у просторі користувача без root. — git.zx2c4.com
Стільниковий рівень та IMS
- GrapheneOS, FAQ, «What are the default connections?» — MMS, RCS, SMS поверх LTE, VVM, VoLTE, VoNR і VoWi-Fi реалізовані операційною системою поверх TCP/IP через IMS. — grapheneos.org
- GrapheneOS, FAQ, «Is the baseband isolated?» — grapheneos.org