Android always-on VPN: hvordan endepunktnavnet blir løst først
Android stenger trafikken før tunnelen finnes, men klienten må fortsatt løse endepunktet. Her er rekkefølgen og punktet der det stopper.
Telefonen starter på nytt, always-on er aktivert, «blokker tilkoblinger uten VPN» er slått på, og tunnelen kommer aldri opp. Det er ikke noe galt med oppsettet: blokkeringen gjør jobben sin, og klientens eget forsøk på å nå endepunktet sitt er også omfattet av den. Endepunktnavnet må løses før tunnelen eksisterer, av en klient som får lov til å snakke med nettverket mens alle andre apper ikke får det. Forståelsen av hvilken komponent som gjør dette, og i hvilken rekkefølge, gjør dette fra et mysterium til et spørsmål om konfigurasjon.
Hva VPN-byggeren egentlig ber om
En Android VPN-app gir ikke plattformen en serveradresse. Den lager et lokalt grensesnitt: adresser og ruter for tunnelen, oppløserne appene skal bruke inni den, og deretter returnerer establish() en fildeskriptor som appen leser og skriver som rå IP-pakker. Det eksterne endepunktet dukker ikke opp i den byggeren i det hele tatt.
Dette er det sentrale strukturelle forholdet. Plattformen oppretter et tun-grensesnitt og håndhever policy på det; appen implementerer transporten i brukerrommet, som betyr at appen selv løser endepunktnavnet og åpner den krypterte forbindelsen. Et endepunkt i form av et vertsnavn er derfor mulig — ikke fordi plattformen støtter navn, men fordi plattformen aldri ser endepunktet.
Ett felt i byggeren tar likevel imot adresser: DNS-serverne. De må være numeriske oppløseradresser, som regel de operatøren ønsker å spørre gjennom tunnelen. Feltet beskriver hvor appene sender spørringer etter at tunnelen er oppe. Det sier ingenting om hvordan klienten finner endepunktet, og å behandle de to som én innstilling er der forvirringen starter.
To DNS-spørsmål, ikke bare ett
Det første spørsmålet er: hvor appene sender spørringene sine når tunnelen er oppe? Svaret er en oppløseradresse inne i tunnelen, tilgjengelig gjennom tun-grensesnittet, og numerisk av natur.
Det andre spørsmålet er: hvordan finner klienten sitt eget endepunkt før den tunnelen finnes? Det oppslaget skjer utenfor tunnelen, på det bakenforliggende nettverket, inne i klientprosessen. Det kan bruke et navn, og det må bruke en oppløser som enheten når uten VPN.
| Stage | Who resolves | Path | Failure looks like |
|---|---|---|---|
| Endpoint lookup | The VPN app | Underlying network, protected socket | Never connects; no tunnel interface traffic |
| Peer authentication | Client and server | Tunnel transport | Connects then drops; certificate or key error |
| Private name lookup | Apps via the tunnel | Resolver inside the tun | Tunnel up, internal sites do not resolve |
Tre faser, tre forskjellige symptomer. Én enkelt feilmelding om at «tilkobling ikke er mulig» smelter dem sammen, og det er grunnen til at folk begynner å redigere DNS-serverfeltet for å rette en feil som skjer før feltet i det hele tatt blir lest.
Hvorfor oppstarten kan låse seg
Always-on med blokkeringen på betyr at trafikk utenfor VPN-en forkastes, også trafikk fra appen som eier VPN-en. Unntaket er uttrykkelig: appen kaller protect() på en socket, og det binder den til det bakenforliggende nettverket slik at den går utenom tunnelen og slipper ut. Enhver VPN-klient må gjøre dette for transporten sin, ellers når den aldri fram til en server.
Se for deg en utrulling der den eneste oppløseren som kjenner endepunktnavnet, ligger inne i tunnelen. Klienten trenger tunnelen for å løse navnet, og navnet for å bygge tunnelen. Dette er en reell sirkulær avhengighet, og ingen klientkonfigurasjon løser den. Det er en designfeil, ikke en feil i programvaren.
Tidspunktet avdekker den samme avhengigheten i mildere varianter. Ved oppstart før første opplåsing har enheten kanskje ikke noe brukbart nettverk ennå; på en captive portal finnes nettverket, men stenger alt unntatt portalen; ved overgang fra Wi-Fi til mobilnett endres det bakenforliggende nettverket til den beskyttede socketen, og klienten må oppdage det og løse på nytt. Hver av disse er en oppstartshendelse, og hver av dem er verdt å teste med vilje i stedet for å oppdage klokken 3 om natten.
Hvorfor det ikke er en løsning å låse svaret
Den fristende snarveien er å løse navnet én gang og lime den resulterende adressen inn i et numerisk felt, eller å hardkode den i et eget bygg. Det ser ut som det virker, og det gjør et navn om til et øyeblikksbilde. Når operatøren flytter endepunktet — en migrering, en anycast-endring, en ny regional adresse — fortsetter klienten å ringe det gamle, og ingenting i grensesnittet forklarer hvorfor.
DNS-oppføringer har levetid nettopp for at svarene skal kunne endre seg; hurtiglagring er definert ut fra den levetiden, ikke for evig. Å låse et svar kaster bort mekanismen som gjør et navn bedre enn en adresse, mens driftskostnaden ved å ha brukt et navn blir stående.
Låsing har også en tendens til å følge med en annen dårlig vane: å lempe på identitetskontrollen fordi forbindelsen nå feiler på en annen måte. Verifisering av serveridentitet er ikke en del av oppstartsproblemet, og å svekke den bytter en DNS-ulempe mot en risiko for avlytting.
Design som tåler en omstart
Den holdbare ordningen er lite prangende. Bruk en klient som implementerer beskyttede socketer korrekt og løser endepunktet sitt på det bakenforliggende nettverket, og gi den et endepunktnavn som løses offentlig, eller gjennom en oppløser som er tilgjengelig før tunnelen. La blokkeringen være på; å slå den helt av for å få DNS til å virke fjerner egenskapen utrullingen er til for.
Der endepunktet må forbli privat, tilby en uttrykkelig oppstartsvei som plattformen kan bruke — en oppløser som er tilgjengelig uten tunnelen, eller en administrasjonsforbindelse som operatøren vedlikeholder — og hold det unntaket smalt og styrt av policy, ikke av en bryter for brukeren. Android VpnService-dokumentasjonen er referansen for hva plattformen garanterer om beskyttelse og livssyklus, og VpnService.Builder-referansen bekrefter at DNS-feltet tar imot numeriske adresser.
Til slutt verifiserer du de tre fasene, i rekkefølge, på en ny forbindelse etter omstart: endepunktnavnet løses, tunnelen etableres og motparten autentiseres, og et privat navn løses gjennom oppløseren i tunnelen. Hvis første fase feiler, kan ingenting senere virke, og rettelsen hører til i oppstartsveien — aldri i oppløserfeltet.
- Oppløsningen av endepunktet skjer i appen, utenfor tunnelen, på en beskyttet socket.
- DNS-feltet i byggeren er for apper inne i tunnelen, ikke for klientens eget endepunkt.
- En oppløser som bare er tilgjengelig via tunnelen, er en fastlåsing, ikke en treg start.
- Test endepunkt, autentisering og privat oppslag hver for seg etter en omstart.