Android-app løser navne uden for VPN: en tjekliste til binding
Android kan løse navne via standardnettet, mens en VPN er aktiv. Bind processen til VPN-nettet, og kontrollér hvilken resolver appen faktisk brugte.
En Android-app kan ikke løse et internt navn, mens VPN-klientens egen browser når det, og samme build virker på en anden telefon. Variablen er ikke URL’en. Variablen er, hvilket netværk app-processen må bruge til opløsning, og Android garanterer ikke, at den aktive VPN er den, dine sockets bruger. Gå disse kontroller igennem i rækkefølge, og stop når resolver-øjebliksbilledet ikke stemmer overens med din antagelse.
Trin 1: Bevis hvilket netværk appen er på
Læs appens eget syn i stedet for statuslinjen. Fra ConnectivityManager hent det aktive netværk, dets LinkProperties , listen over DNS-servere og indstillingen for privat DNS. Hvis listen indeholder VPN’ens resolver, har appen en vej til den; hvis den indeholder Wi-Fi-resolveren, er tunnelen ikke standardnettet for den proces.
Et VPN-ikon siger kun, at der findes en tunnel. Det siger ikke, at appens proces blev bundet til den, og Android sender ikke altid navneopløsning gennem det netværk, der ser aktivt ud. Lokale VPN-apps, der videresender til en anden enhed, Wi-Fi-netværk uden internet og producenters builds kan alle få en app til at spørge standardresolveren i stedet for tunnelens servere.
Trin 2: Anmod om VPN-transporten, og bind processen
Når appen skal bruge tunnelens resolver, anmod om et netværk med VPN-transporten, og bind processen i callbacket, så koden ikke gætter på, hvornår netværket dukker op:
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)
}
})Kaldet ændrer standardnettet for hele processen, så hver socket, der oprettes bagefter, bruger det. Sockets, der allerede findes, beholder det netværk, de blev oprettet på, og derfor kan en forbindelsespulje, der blev åbnet før bindingen, fortsætte med at løse via den gamle vej. Returværdien er en boolean, og et false betyder, at bindingen ikke skete; prøv igen efter en kort forsinkelse, og log begge forsøg.
Trin 3: Begræns bindingen til det, der har brug for den
Binding på hele processen er grov. Telemetri, opdateringstjek og tredjeparts-SDK’er flytter også til tunnelen, og hvis tunnelen ikke har internet, begynder de at fejle. Til en enkelt anmodning brug netværkets socket-fabrik, og behold enhedens standard for alt andet. Vælg bevidst én model: en snæver binding pr. forbindelse eller en procesbinding med eksplicit unbind, når VPN’en forsvinder.
To resolverfunktioner kan besejre bindingen uden nogen fejl. Privat DNS i streng tilstand sender forespørgsler til en navngivet DoT-server i stedet for netværksresolveren, og en app med sin egen DNS-over-HTTPS-klient omgår systemets resolver helt. Kontrollér begge, før du konkluderer, at bindingen fejlede. En forespørgsel, der aldrig når VPN’ens DNS-server, vises ikke i nogen log på tunnelsiden.
Trin 4: Stol ikke på en CONNECTED-betingelse
Flaget NetworkType.CONNECTED i WorkManager betyder, at et netværk er forbundet, og VPN-transporten opfylder det, selv når det underliggende Wi-Fi- eller mobillink er væk. Jobbet kører, hver anmodning fejler, og retry-politikken gør det til en storm, der ligner en planlægningsfejl. Tunnelen er et netværk; betingelsen var aldrig et internet-tjek.
Kontrollér den egenskab, arbejdet faktisk har brug for, fx valideret internetadgang, og hold en begrænset retry-politik med backoff. Hvis jobbet har brug for et internt navn, skal du løse det navn i det valgte netværk, før du udfører arbejdet, og fejle hurtigt med en klar fejl i stedet for at gentage en anmodning, der ikke kan lykkes.
Trin 5: Registrér beviserne, og test rækkevidden igen
Log det valgte netværks transporttyper, DNS-serverne fra LinkProperties , om bindingen returnerede true, og den første anmodnings præcise fejl. Kør derefter et internt og et offentligt navn under samme binding. Det par viser, om appen brugte tunnelens resolver eller stille faldt tilbage til enhedens standard, og det er den forskel, brugeren oplever.
Gentag på den ældste Android-version, du understøtter, og på en aktuel version. Den resolveradfærd, der får standardvejen til at se korrekt ud, er præcis der, enheder og versioner adskiller sig, og et build, der kun består på den nyeste testenhed, er ikke verificeret for det område, du udgiver. adb shell dumpsys connectivityer en hurtig måde at bekræfte, hvilke netværk og egenskaber enheden rapporterer, mens du genskaber fejlen.