Представьте: ваше корпоративное приложение должно получить доступ к внутреннему API компании через публичный интернет, но разворачивать полноценный device-level VPN на BYOD-устройствах вы не готовы. Нужен туннель только для трафика конкретного приложения — остальное идёт напрямую. Это и есть Per-App VPN, и мы реализовали его уже в 15+ проектах, обеспечив 99.9% uptime туннеля. Для компаний из финтеха, ритейла и логистики мы внедрили такие решения, сократив их расходы на корпоративную связь до $10,000 в год.
Как реализовать Per-App VPN на Android и iOS
Android: VpnService
На Android Per-App 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 — туннель работает для всех приложений кроме указанных. Нужно точно понимать, какой сценарий требует заказчик.
iOS: Network Extension и необходимость MDM
На iOS всё иначе. Apple не даёт прямого доступа к TUN-интерфейсу из обычного приложения. Per-App VPN реализуется через Network Extension framework — конкретно 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.
Почему на iOS нужен MDM?
Согласно официальной документации Apple, Per-App VPN на iOS требует наличия MDM-профиля с опцией PerAppVPN. Без него невозможно ограничить туннель конкретным приложением. Если MDM недоступен, единственный вариант — device-level VPN с ручной настройкой split-tunneling, но это не обеспечивает полной изоляции.
Выбор протокола: WireGuard, OpenVPN или IKEv2
Выбор протокола зависит от требований к скорости, безопасности и совместимости. WireGuard обеспечивает высокую скорость и современное шифрование, но на iOS работает только через Network Extension. OpenVPN совместим со всеми платформами, но медленнее. IKEv2 нативно поддерживается iOS, что упрощает настройку. Сравните:
| Протокол | Скорость | Безопасность | Совместимость |
|---|---|---|---|
| WireGuard | Высокая | Высокая (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.9%.
Что делать при краше расширения на 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 |
Процесс внедрения
- Аналитика: уточняем протокол шлюза, 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 недель. Стоимость рассчитывается индивидуально после аудита вашей инфраструктуры. Если сравнить с арендой выделенного VPN-сервера, наше решение окупается за 2-3 месяца. Экономия на трафике составляет до $5,000 в год.
Наш опыт и как начать
Мы внедрили Per-App VPN для 15+ компаний (финтех, ритейл, логистика). Опыт работы с iOS и Android — 5+ лет. Гарантируем стабильную работу туннеля при корректной настройке MDM и шлюза. Предоставляем письменные гарантии на код и поддержку.
Свяжитесь с нами для консультации — получите бесплатный аудит вашей инфраструктуры и оценку проекта.







