VPN для окремих застосунків в Android: виключити застосунок не означає заблокувати його
Список застосунків на екрані належить одному власнику тунелю, і виключення застосунку спрямовує його в обхід цього тунелю, а не відключає від мережі. Почніть звідти.
Двоє людей ставлять те саме питання й отримують несумісні відповіді, бо стоять у різних місцях. В одного відкритий екран системних налаштувань VPN, і він редагує список застосунків. Інший пише VpnService.Builder.addDisallowedApplication() у редакторі. Обидва називають це VPN-фільтром за застосунками. Лише один із них володіє тим керуванням, яке описує, і жоден нічого не блокує.
Почніть з екрана, який бачить користувач
Відкрийте Налаштування, знайдіть пункт VPN і подивіться на з єднання, яке справді активне. Якщо клієнт пропонує список за застосунками, цей список належить власному тунелю клієнта. Платформа не публікує загального API, через який сторонній застосунок міг би читати або змінювати вибір застосунків іншого VPN, тож другий застосунок не може виправити цей список за користувача.
Це перше розгалуження в розборі. Якщо у встановленого VPN немає такого налаштування, обходити кодом нічого: функції немає в продукті, якому належить тунель. Якщо є, правильне виправлення на цьому екрані, і робить його той, хто може його відкрити.
Простежте пакет у тунель
Коли ваш застосунок будує тунель, він створює інтерфейс TUN і оголошує, чий трафік до нього входить. Виклики членства відбуваються до встановлення інтерфейсу, а після цього набір правил фіксується на цю сесію:
val builder = VpnService.Builder()
builder.addAddress("10.8.0.2", 32)
builder.addRoute("0.0.0.0", 0)
builder.addDisallowedApplication("com.example.bypass")
val tun = builder.establish() // membership decided hereЦі виклики стосуються лише тунелю, який ваш застосунок щойно створив, і нічого більше. Вони не є політикою всього пристрою, не зберігаються для інших клієнтів і не можуть дістатися чужого VPN. Коли виклик конструктора викидає виняток через те, що пакет не вдається розв язати, інтерфейс так і не встановлюється, і це чиста, а не тиха відмова.
Чому виключення виглядало як блокування
Виключений застосунок спрямовується в обхід вашого тунелю в мережу під ним. Це протилежність блокуванню: трафік усе ще залишає пристрій, просто поза інтерфейсом, яким ви керуєте. Застосунок у стилі міжмережевого екрана робить навпаки. Він впускає трафік застосунку до свого тунелю, а потім відкидає пакети або відмовляється їх пересилати, тож інтерфейс той самий, а напрям політики обернений.
Робота за цим перевертанням не є прапорцем конфігурації. Ви читаєте IP-пакети з дескриптора тунелю, вирішуєте для кожного потоку, а потім пересилаєте їх через захищений сокет або відкидаєте. Усе, що ви не обробили, просто зупиняється, і саме тому недобудований тунель виглядає як зламана мережа, а не як робочий фільтр. Якщо мета блокування, закладайте обробку пакетів, службу переднього плану й письмову політику для трафіку, який ви не можете класифікувати.
Що ламається, коли ви будуєте це самі
Android зазвичай дозволяє лише один активний VPN одночасно, тож ваш фільтрувальний тунель і тунель приватності конкурують за одне місце, якщо продукти не підтримують ланцюгування. Постійний VPN із блокуванням з єднань змінює характер відмови так, як тут важливо: трафік, який не може увійти в тунель, відкидається замість прямої відправки, чого хоче схема захисту від витоків і чого сесія налагодження майже не чекає.
Видимість пакетів друга пастка. Розв язання назви пакета застосунку може завершитися помилкою NameNotFoundException, а в нових версіях Android набір видимих пакетів залежить від оголошених вами запитів. Обробляйте виняток замість припущення, що кожна назва розв яжеться, і перечитуйте список під час встановлення чи видалення застосунків, а не тримайте його в кеші вічно.
Керовані пристрої додають третього власника Політика корпоративної мобільності може задати VPN за застосунками або профіль постійного підключення, і звичайний застосунок не може це перевизначити. Перевірте, чи пристрій керований, перш ніж налагоджувати власний код, бо в цьому разі список, який ви намагаєтеся змінити, може бути недоступним для редагування нікому, хто тримає телефон.
Перевірте це на застосунку, яким керуєте ви
Не тестуйте на застосунку, який намагаєтеся фільтрувати. Візьміть другий застосунок, чию мережеву поведінку ви можете спостерігати, і перевірте, чи його трафік виходить через ваш тунель, тоді як трафік цілі ні. Якщо обидва залишаються всередині, політика працює і ціль виключена; якщо не виходить жоден, неправильний сам тунель, а список застосунків ні до чого.
Потім вирішіть, що саме з трьох речей ви будуєте. Тунель за застосунками це API конструктора, а список є частиною вашого профілю. Міжмережевий екран пристрою це обробка пакетів плюс життєвий цикл, який ви можете захистити. Змінювати чужий VPN взагалі не підтримуваний шлях, і чесна відповідь там полягає в тому, що це налаштування належить тому продукту.