Приложение за Android разрешава имена извън VPN: контролен списък за обвързване
Android може да разрешава имена през мрежата по подразбиране, докато VPN е включен. Обвържете процеса с VPN мрежата и проверете кой резолвер е използвало приложението.
Приложение за Android не успява да разреши вътрешно име, докато собственият браузър на VPN клиента го достига, а същата сборка работи на друг телефон. Променливата не е URL адресът. Променливата е коя мрежа е разрешено да използва процесът на приложението за разрешаване и Android не гарантира, че активният VPN е този, който използват вашите сокети. Изпълнете тези проверки по ред и спрете, когато моментната картина на резолвера не съвпада с предположението ви.
Стъпка 1: Докажете в коя мрежа е приложението
Четете собствената гледна точка на приложението, а не лентата за състояние. От ConnectivityManager вземете активната мрежа, нейните LinkProperties , списъка с DNS сървъри и настройката за частен DNS. Ако списъкът съдържа резолвера на VPN, приложението има път до него; ако съдържа резолвера на Wi-Fi, тунелът не е мрежата по подразбиране за този процес.
Иконата на VPN казва само, че има тунел. Тя не казва, че процесът на приложението е обвързан с него, и Android не винаги насочва разрешаването на имена през мрежата, която изглежда активна. Локални VPN приложения, които препращат към друго устройство, Wi-Fi мрежи без интернет и сборки на производители могат да оставят приложението да пита резолвера по подразбиране вместо сървърите на тунела.
Стъпка 2: Поискайте VPN транспорта и обвържете процеса
Когато приложението трябва да използва резолвера на тунела, поискайте мрежа с VPN транспорта и обвържете процеса в callback, за да не гадае кодът кога се появява мрежата:
val request = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_VPN)
.build()
connectivityManager.requestNetwork(request, object : NetworkCallback() {
override fun onAvailable(network: Network) {
val bound = connectivityManager.bindProcessToNetwork(network)
Log.i(TAG, "bound to VPN network: " + bound)
}
})Извикването променя мрежата по подразбиране за целия процес, така че всеки сокет, създаден след това, я използва. Вече съществуващите сокети запазват мрежата, в която са създадени, затова пул от връзки, отворен преди обвързването, може да продължи да разрешава по стария път. Върнатата стойност е boolean и резултат false означава, че обвързването не се е случило; опитайте отново след кратко закъснение и запишете и двата опита.
Стъпка 3: Ограничете обвързването до това, което го изисква
Обвързването за целия процес е грубо. Телеметрията, проверките за обновяване и SDK на трети страни също минават през тунела и ако тунелът няма интернет, започват да се провалят. За единична заявка използвайте фабриката за сокети на мрежата и запазете устройството по подразбиране за всичко останало. Изберете съзнателно един модел: тясно обвързване за всяка връзка или обвързване на процеса с явно отвързване, когато VPN изчезне.
Две функции на резолвера могат да победят обвързването без никаква грешка. Частният DNS в строг режим изпраща заявки към именуван DoT сървър вместо към резолвера на мрежата, а приложение със свой клиент за DNS-over-HTTPS напълно заобикаля системния резолвер. Проверете и двете, преди да заключите, че обвързването е неуспешно. Заявка, която никога не достига DNS сървъра на VPN, няма да се появи в нито един журнал от страна на тунела.
Стъпка 4: Не се доверявайте на ограничение CONNECTED
Флагът NetworkType.CONNECTED на WorkManager означава, че има свързана мрежа и VPN транспортът го удовлетворява дори когато основната Wi-Fi или клетъчна връзка е изчезнала. Задачата се изпълнява, всяка заявка се проваля и политиката за повторение я превръща в буря, която изглежда като грешка в планирането. Тунелът е мрежа; ограничението никога не е било проверка за интернет.
Проверете възможността, която задачата наистина изисква, например потвърден достъп до интернет, и поддържайте ограничена политика за повторение с отстъпване. Ако задачата се нуждае от вътрешно име, разрешете това име в избраната мрежа преди да свършите работата и се провалете бързо с ясна грешка вместо да повтаряте заявка, която не може да успее.
Стъпка 5: Запишете доказателствата и тествайте обхвата отново
Запишете типовете транспорт на избраната мрежа, DNS сървърите от LinkProperties , дали обвързването е върнало true и точния отказ на първата заявка. След това изпълнете вътрешно и публично име при същото обвързване. Тази двойка показва дали приложението е използвало резолвера на тунела или тихо е паднало към устройството по подразбиране и това е разликата, която потребителят усеща.
Повторете на най-старата версия на Android, която поддържате, и на една текуща версия. Поведението на резолвера, което прави пътя по подразбиране да изглежда правилен, е точно там, където устройствата и версиите се различават, а сборка, която минава само на най-новото тестово устройство, не е проверена за обхвата, който доставяте. adb shell dumpsys connectivityе бърз начин да потвърдите кои мрежи и възможности отчита устройството, докато възпроизвеждате отказа.