En Android-app klarer ikke å løse et internt navn mens nettleseren i selve VPN-klienten kommer seg dit, og den samme byggingen virker på en annen telefon. URL-en er ikke den variabelen. Variabelen er hvilket nettverk appens prosess får bruke til navneoppslag, og Android garanterer ikke at den aktive VPN-en er nettverket socketene dine bruker. Utfør disse kontrollene i rekkefølge, og stopp når resolver-bildet ikke stemmer med det du forventet.

Trinn 1: vis hvilket nettverk appen ligger på

Les appens egen framstilling i stedet for statuslinjen. Hent det aktive nettverket fra ConnectivityManager, sammen med LinkProperties for det, listen over DNS-tjenere og innstillingen for privat DNS. Inneholder listen VPN-ens resolver, har appen en vei dit; inneholder den Wi-Fi-ens resolver, er ikke tunnelen standardnettverket for den prosessen.

Et VPN-symbol forteller bare at en tunnel eksisterer. Det sier ingenting om at appens prosess var knyttet til den, og Android sender 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 produsentene kan alle etterlate appen med å spørre standardresolveren i stedet for tjenerne i tunnelen.

Trinn 2: be om VPN-transport og bind prosessen

Når appen er nødt til å bruke resolveren i tunnelen, be om et nettverk med VPN-transport og bind prosessen i tilbakemeldingen, 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 bytter standardnettverket for hele prosessen, og dermed bruker hver socket som lages etterpå, dette nettverket. Socket-er som allerede finnes, beholder nettverket de ble laget på, og derfor kan en forbindelsespool som ble åpnet før bindingen, fortsette å slå opp via den gamle veien. Returverdien er en boolean, og svaret false betyr at bindingen ikke fant sted; forsøk på nytt etter en kort pause og loggfør begge forsøkene.

Trinn 3: hold bindingen innenfor det som trenger den

Binding av hele prosessen er rått. Telemetri, oppdateringssjekker og SDK-er fra tredjeparter flytter også over på tunnelen, og dersom tunnelen mangler internett, begynner de å svikte. For en enkelt forespørsel bruker du nettverkets socket-fabrikk og lar enhetens standard gjelde for alt annet. Velg én modell med vilje: en smal binding per tilkobling, eller en prosessbinding med tydelig oppheving når VPN-en forsvinner.

To egenskaper ved resolveren kan overvinne bindingen uten at det gis noen feil. Privat DNS i streng modus sender spørringer til en navngitt DoT-tjener i stedet for nettverkets resolver, og en app som leverer sin egen DNS-over-HTTPS-klient, går helt utenom systemets resolver. Sjekk begge før du konkluderer med at bindingen feilet. En spørring som aldri når VPN-ens DNS-tjener, vil ikke dukke opp i noen logg på tunnelsiden.

Trinn 4: ikke stol på en CONNECTED-betingelse

NetworkType.CONNECTED i WorkManager betyr at et nettverk er tilkoblet, og VPN-transporten tilfredsstiller den selv om den underliggende Wi-Fi- eller mobilforbindelsen er borte. Jobben kjører, alle forespørsler feiler, og retry-politikken gjør det hele til en storm som ser ut som en feil i planleggingen. Tunnelen er et nettverk; betingelsen var aldri en internettkontroll.

Sjekk evnen arbeidet faktisk trenger, for eksempel bekreftet internettilgang, og hold en avgrenset retry-politikk med backoff. Dersom jobben trenger et privat navn, må du slå opp navnet i det valgte nettverket før arbeidet utføres, og feile raskt med en tydelig feil i stedet for å gjenta en forespørsel som ikke kan lykkes.

Trinn 5: før bevisene inn og test området på nytt

Loggfør transporttypene til det valgte nettverket, DNS-tjenerne fra LinkProperties, om bindingen returnerte true, og den nøyaktige feilen ved den første forespørselen. Deretter kjører du et privat navn og et offentlig navn under samme binding. Det paret viser om appen brukte tunnelens resolver eller stille falt tilbake på enhetens standard, og det er forskjellen brukeren merker.

Gjenta på den eldste Android-versjonen du støtter, og på én gjeldende utgivelse. Resolver-oppførselen som får standardveien til å se korrekt ut, er nettopp der enheter og versjoner spriker, og en bygging som bare passerer på den nyeste testenheten, er ikke verifisert for det området du sender ut. adb shell dumpsys connectivity er en rask måte å bekrefte hvilke nettverk og evner enheten rapporterer mens du gjenskaper feilen.

Relaterte artikler