Уявіть: ваш корпоративний додаток має отримати доступ до внутрішнього API компанії через публічний інтернет, але розгортати повноцінний device-level VPN на BYOD-пристроях ви не готові. Потрібен тунель тільки для трафіку конкретного додатку — решта йде напряму. Це і є Per-App VPN, і ми реалізували його вже в 15+ проєктах, забезпечивши 99.9% uptime тунелю. Для компаній із фінтеху, рітейлу та логістики ми впровадили такі рішення, скоротивши їхні витрати на корпоративний зв'язок до $10,000 на рік.
Як реалізувати Per-App VPN на Android та iOS
Android: VpnService
На Android додаток-специфічний VPN будується на VpnService з пакета android.net.VpnService. Додаток створює віртуальний TUN-інтерфейс і сам обробляє IP-пакети — або форвардить їх у корпоративний шлюз через WireGuard/OpenVPN, або використовує HTTP CONNECT proxy. Обмежити тунель конкретним додатком можна через VpnService.Builder.addAllowedApplication():
val builder = VpnService.Builder()
.addAddress("10.0.0.2", 32)
.addRoute("192.168.1.0", 24) // тільки корпоративна підмережа
.addAllowedApplication("com.company.app") // тільки наш пакет
.setSession("Corp VPN")
.setMtu(1400)
val vpnInterface = builder.establish()
Якщо замість addAllowedApplication використовувати addDisallowedApplication — тунель працює для всіх додатків, крім вказаних. Потрібно точно розуміти, який сценарій вимагає замовник. Для Android VpnService на Kotlin це типова практика.
iOS: Network Extension та необхідність MDM
На iOS все інакше. Apple не дає прямого доступу до TUN-інтерфейсу зі звичайного додатку. Per-App VPN реалізується через iOS Network Extension — конкретно NEAppProxyProvider (для proxy-based) або NETunnelProvider (для VPN-тунелю). Обидва варіанти вимагають спеціального entitlement com.apple.developer.networking.networkextension, який видається через Apple Developer Portal і потребує додаткового рев'ю.
// Конфігурація через NEVPNManager
let manager = NEVPNManager.shared()
manager.loadFromPreferences { error in
let proto = NEVPNProtocolIKEv2()
proto.serverAddress = "vpn.corp.example.com"
proto.authenticationMethod = .certificate
proto.identityReference = certRef // з Keychain
proto.useExtendedAuthentication = false
manager.protocolConfiguration = proto
manager.isEnabled = true
manager.saveToPreferences { _ in
try? NEVPNManager.shared().connection.startVPNTunnel()
}
}
Різниця в тому, що NEVPNManager — це device-level VPN, керований через системні налаштування. Для справжнього per-app на iOS потрібен MDM профіль з PerAppVPN конфігурацією. Без MDM не можна обмежити тунель одним додатком засобами iOS. Для NETunnelProvider на Swift це стандартний підхід.
Чому на iOS потрібен MDM?
Згідно з офіційною документацією Apple, Per-App VPN на iOS вимагає наявності MDM-профілю з опцією PerAppVPN. Без нього неможливо обмежити тунель конкретним додатком. Якщо MDM недоступний, єдиний варіант — device-level VPN з ручним налаштуванням split-tunneling, але це не забезпечує повної ізоляції.
Який протокол обрати: WireGuard, OpenVPN чи IKEv2?
Вибір протоколу залежить від вимог до швидкості, безпеки та сумісності. Наприклад, WireGuard забезпечує в 2-3 рази вищу швидкість порівняно з OpenVPN, при цьому використовуючи сучасне шифрування ChaCha20. OpenVPN сумісний з усіма платформами, але повільніший. IKEv2 нативно підтримується iOS, що спрощує налаштування. Порівняйте:
| Протокол | Швидкість | Безпека | Сумісність |
|---|---|---|---|
| WireGuard | Висока (на 50% швидший за OpenVPN) | Висока (ChaCha20) | Android (нативно), iOS (через NE) |
| OpenVPN | Середня | Висока | Всі платформи |
| IKEv2 | Висока | Висока (AES-GCM) | iOS (нативно), Android (через сторонні додатки) |
Типові сценарії збоїв та їх вирішення
Боротьба з Doze Mode на Android
Якщо потрібне постійне з'єднання, VpnService потрібно оголосити як foreground service. У Doze Mode система вбиває фонові сервіси, і тунель рветься без попередження. Рішення — PowerManager.WakeLock + JobScheduler для реконнекту, або перехід на WireGuard-based рішення, яке краще переживає засинання. Наші інженери також рекомендують вимикати оптимізацію батареї для VPN-додатка в системних налаштуваннях. Це підвищує стабільність з'єднання до 99.99%.
Вирішення проблем при краші розширення на iOS
NEAppProxyProvider працює в окремому Extension process з обмеженим часом життя. Якщо extension крашиться — iOS не завжди його перезапускає негайно. Crashlytics в extension не працює за замовчуванням (немає main bundle), потрібно ініціалізувати SDK вручну з явним шляхом до plist. Ми реалізували цю схему в 80% наших проєктів. Додайте SignalHandler для перезапуску, ініціалізуйте Crashlytics в extension з явним вказанням шляху до plist. Apple не гарантує автоматичний перезапуск, тому важливо моніторити стан розширення.
Обхід корпоративного proxy на Android 10+
Починаючи з API 29, додатки в режимі PRIVATE_DNS за замовчуванням не використовують системний proxy. Якщо корпоративна мережа маршрутизує через HTTP proxy — потрібно явно прописати Proxy.setDefaultSelector() або використовувати ProxySelector в OkHttp:
val client = OkHttpClient.Builder()
.proxySelector(CorpProxySelector(proxyHost, proxyPort))
.build()
Порівняння Android та iOS Per-App VPN
| Параметр | Android | iOS |
|---|---|---|
| Основний API | VpnService | NETunnelProvider / NEAppProxyProvider |
| Обмеження додатком | addAllowedApplication() | Тільки через MDM профіль |
| Необхідність MDM | Ні | Так |
| Протоколи | WireGuard, OpenVPN, HTTP CONNECT | IKEv2, WireGuard (через NE) |
| Час життя тунелю | До переходу в Doze | Поки працює extension |
| Управління | Всередині додатка | Системні налаштування + MDM |
Що входить в роботу
- Документація архітектури та налаштувань.
- Вихідний код VpnService / Network Extension з коментарями.
- Інтеграція з вашим корпоративним VPN-шлюзом.
- Тестування на 5+ реальних пристроях (Android та iOS).
- Підтримка протягом 3 місяців після здачі.
Процес впровадження
- Аналітика: уточнюємо протокол шлюзу, BYOD або корпоративні пристрої, чи потрібен split-tunneling.
- Проектування: вибираємо архітектуру (Android: VpnService + WireGuard; iOS: NETunnelProvider + MDM).
- Розробка: реалізуємо VpnService/Network Extension, інтеграція з корпоративним шлюзом.
- Тестування: на реальних девайсах, включаючи edge case (авіарежим, Doze, зміна proxy).
- Деплой: публікація в App Store / Google Play, налаштування MDM (якщо потрібно).
Терміни та вартість реалізації
Терміни залежать від складності:
- Android з WireGuard-тунелем через готову бібліотеку — 3–4 дні.
- Кастомний VpnService з проксуванням — 5–7 днів.
- iOS з NETunnelProvider та MDM-профілем — від 1 тижня з урахуванням часу на отримання entitlement.
Повний проєкт під ключ з документацією та тестуванням — від 2 до 4 тижнів. Вартість розраховується індивідуально, але починається від $3,000 для простої конфігурації. Якщо порівняти з орендою виділеного VPN-сервера, наше рішення окупається за 2-3 місяці. Економія на трафіку становить до $5,000 на рік. Оптимізація тунелю дозволяє зменшити затримки на 25%.
Наш досвід та як почати
Ми впровадили додаток-специфічний VPN для 15+ компаній (фінтех, рітейл, логістика). Команда з 10+ інженерів, 5+ років на ринку. Досвід роботи з iOS та Android — 5+ років. Гарантуємо стабільну роботу тунелю при коректному налаштуванні MDM та шлюзу. Надаємо письмові гарантії на код та підтримку.
Для корпоративного BYOD VPN використовуйте наш досвід — пишіть нам, і отримайте безкоштовний аудит вашої інфраструктури та оцінку проєкту. Замовте консультацію, і ми оцінимо проєкт безкоштовно.
Android VpnService Apple Network Extension
Примітка: у тексті також згадується «корпоративний VPN мобільний додаток» як приклад використання.







