Android-app løser navn utenfor VPN-en: sjekkliste for binding
Android kan løse navn gjennom standardnettverket mens VPN-en er aktiv. Bind prosessen til VPN-nettverket og bekreft hvilken resolver appen faktisk brukte.
En Android-app får ikke løst et internt navn mens nettleseren til selve VPN-klienten når det, og samme bygg fungerer på en annen telefon. URL-en er ikke variabelen. Variabelen er hvilket nettverk prosessen til appen har lov til å bruke for oppslag, og Android garanterer ikke at den aktive VPN-en er nettverket socketene dine bruker. Gjør disse kontrollene i rekkefølge og stopp når resolver-øyeblikksbildet ikke stemmer med antakelsen din.
Trinn 1: bevis hvilket nettverk appen er på
Les appens egen visning i stedet for statuslinjen. Fra ConnectivityManager henter du det aktive nettverket, LinkProperties for det, listen over DNS-servere og innstillingen for privat DNS. Hvis listen inneholder resolveren til VPN-en, har appen en vei til den; hvis den inneholder resolveren til Wi-Fi, er tunnelen ikke standardnettverket for den prosessen.
Et VPN-ikon sier bare at en tunnel finnes. Det sier ikke at prosessen til appen var bundet til den, og Android ruter ikke alltid navneoppslag gjennom nettverket som ser aktivt ut. Lokale VPN-apper som videresender til en annen enhet, Wi-Fi-nettverk uten internett og bygg fra leverandøren kan alle la appen spørre standardresolveren i stedet for serverne til tunnelen.
Trinn 2: be om VPN-transporten og bind prosessen
Når appen må bruke resolveren til tunnelen, ber du om et nettverk med VPN-transport og binder prosessen i tilbakeringingen, slik at koden ikke gjetter når nettverket dukker opp:
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)
}
})
Kallet endrer standardnettverket for hele prosessen, så hver socket som opprettes etterpå, bruker det. Socket-er som allerede finnes, beholder nettverket de ble opprettet på, og derfor kan en tilkoblingspool som ble åpnet før bindingen, fortsette å løse via den gamle veien. Returverdien er en boolean, og et resultat på false betyr at bindingen ikke skjedde; prøv igjen med en kort forsinkelse og logg begge forsøkene.
Trinn 3: begrens bindingen til det som trenger den
Binding for hele prosessen er grov. Telemetri, oppdateringskontroller og SDK-er fra tredjepart flytter også over til tunnelen, og hvis tunnelen ikke har internett, begynner de å feile. For én forespørsel bruker du socket-fabrikken til nettverket og lar standarden til enheten gjelde for alt annet. Velg bevisst én modell: smal binding per tilkobling, eller prosessbinding med en tydelig avbinding når VPN-en forsvinner.
To resolverfunksjoner kan slå bindingen uten noen feil. Privat DNS i streng modus sender spørringer til en navngitt DoT-server i stedet for resolveren til nettverket, og en app som har sin egen DNS-over-HTTPS-klient, går helt utenom resolveren i systemet. Sjekk begge før du konkluderer med at bindingen mislyktes. En spørring som aldri når DNS-serveren til VPN-en, vil ikke dukke opp i noen logg på tunnelsiden.
Trinn 4: ikke stol på et CONNECTED-vilkår
NetworkType.CONNECTED i WorkManager betyr at et nettverk er tilkoblet, og VPN-transporten oppfyller det selv når den underliggende Wi-Fi- eller mobillenken er borte. Jobben kjører, hver forespørsel feiler, og retry-policyen gjør det til en storm som ser ut som en planleggingsfeil. Tunnelen er et nettverk; vilkåret var aldri en internettkontroll.
Sjekk evnen som arbeidet faktisk trenger, for eksempel bekreftet internettilgang, og hold på en begrenset retry-policy med backoff. Hvis jobben trenger et privat navn, løs det navnet i det valgte nettverket før du gjør arbeidet, og feil raskt med en tydelig feil i stedet for å gjenta en forespørsel som ikke kan lykkes.
Trinn 5: registrer bevisene og test området på nytt
Logg transporttypene til det valgte nettverket, DNS-serverne fra LinkProperties, om bindingen returnerte true, og den nøyaktige feilen til den første forespørselen. Kjør så et privat navn og et offentlig navn under samme binding. Det paret viser om appen brukte resolveren til tunnelen eller falt stille tilbake til standarden til enheten, og det er forskjellen brukeren opplever.
Gjenta på den eldste Android-versjonen du støtter, og på én gjeldende utgivelse. Oppførselen til resolveren som får standardveien til å se riktig ut, er nettopp der enheter og versjoner skiller seg, og et bygg som bare går gjennom på den nyeste testenheten, er ikke bekreftet for området du sender ut. adb shell dumpsys connectivity er en rask måte å bekrefte hvilke nettverk og evner enheten rapporterer mens du reproduserer feilen.