Android-VPN kjører IPv6, men nettleseren velger fortsatt IPv4
Følg de fire trinnene der en privat IPv6-adresse forsvinner: resolveren, VpnService-erklæringen, nettleserens kandidatsjekk og ruteleveringen.
VPN-et er oppe, det private webgrensesnittet svarer over IPv6 fra en bærbar PC, og Android-telefonen åpner fortsatt samme side over IPv4 eller nekter å laste den helt. AAAA-posten finnes. Tunnelen rapporterer en IPv6-adresse. Ingenting i klienten ser feil ut. Fire separate beslutninger avgjør resultatet: hvilken resolver som svarte, hva VpnService erklærte til Android, hvilken adressefamilie nettleseren var villig til å prøve, og om en pakke klarer turen frem og tilbake. Ta dem i den rekkefølgen i stedet for å legge til en standardrute og håpe at symptomet flytter seg.
Trinn 1: bevis hvilken resolver som svarte på AAAA-spørringen
Android har ikke én enkelt DNS-vei. Et VPN kan skyve en DNS-server til nettverket sitt, systemet kan bruke Private DNS for vertsnavn det anser som kvalifiserte, og Chrome kan kjøre sin egen krypterte resolver fra chrome://settings/security. På en telefon der tunnelen skyver 10.61.0.1, men Private DNS peker på en offentlig leverandør, blir navnet i sonen din ikke slått opp av maskinen som eier sonen. Nettleseren får et svar fra en resolver uten myndighet over navnet og behandler det som manglende, og feilteksten nevner aldri DNS.
Spør tunnelens resolver direkte før du endrer noe annet. De to første kommandoene viser hvilke DNS-servere Android knyttet til det aktive nettverket og om Private DNS er i automatisk eller streng modus; den tredje kjøres fra en hvilken som helst klient inne i tunnelen, ikke fra telefonen.
adb shell dumpsys connectivity | grep -A3 "DnsAddresses"
adb shell settings get global private_dns_mode
nslookup -type=AAAA nas.lan 10.61.0.1
Trinn 2: les hva VpnService faktisk erklærte
Android-siden er eksplisitt og ikke utledet. En VpnService.Builder legger til adresser med addAddress, ruter med addRoute, DNS-servere med addDnsServer, og kan begrense hele tunnelen til én adressefamilie med allowFamily. En bygger som kalte allowFamily(AF_INET) og senere la til en IPv6-rute, har fortalt systemet to motstridende ting, og det er familierestriksjonen systemet beholder. En rute som dekker fd00:61::/64 kombinert med en grensesnittadresse i et annet prefiks feiler av en lignende grunn: adressen finnes, men den er ikke on-link for den ruten.
Les erklæringen i stedet for å stole på bryteren i appen. dumpsys netd skriver ut adressene og rutene som er knyttet til tun-grensesnittet, og LinkProperties per nettverk i dumpsys connectivity viser DNS-listen ved siden av familiene nettverket hevder.
adb shell ip -6 addr show tun0
adb shell ip -6 route show table all | grep tun0
adb shell dumpsys connectivity | grep -E "LinkAddresses|Routes"
Hvis tun-grensesnittet har en IPv6-adresse, men ingen rute samsvarer med tjenestens prefiks, er IPv6-leveringen allerede brutt før en nettleser er involvert. Det er en annen feil enn en nettleser som nekter å prøve, og den krever en annen retting.
Trinn 3: nettleseren avgjør om den vil prøve IPv6 i det hele tatt
Chromium bruker ikke hver AAAA-post den mottar. Vertsresolveren har IPv6-rekkeviddetester og kandidatfiltrering som kan droppe eller nedprioritere IPv6 når nettverket vurderes som ute av stand til å bære det, og resolverens kildekode viser den testen sammen med betingelsene rundt. Logikken avhenger av versjon og flagg, og det er nettopp derfor to telefoner på samme tunnel kan oppføre seg ulikt. Når kandidatene finnes, lar Happy Eyeballs familiene konkurrere per tilkobling, så en IPv6-vei som svarer sakte kan fortsatt tape mot IPv4 som svarer raskt.
Observer beslutningen i stedet for å utlede den. En økt tatt opp via chrome://net-export og spilt av i netlog-viseren viser hver oppslagning og den valgte familien; chrome://net-internals/#dns viser de bufrede resultatene. En oppslagning som bare returnerer A-poster for et navn som har AAAA hos din egen resolver, peker rett på dette trinnet.
Trinn 4: verifiser at en pakke klarer turen frem og tilbake
Adressevalg er ikke levering. Android holder rutetabeller og policyregler per nettverk som velger tabell etter fwmark, så en rute som er synlig i hovedtabellen er ikke automatisk den ruten en socket bruker. Å lese reglene og be kjernen slå opp en destinasjon for en kildeadresse skiller de to.
adb shell ip -6 rule show
adb shell ip -6 route get fd00:61::20 from fd00:61::10
Det er utdataene fra route get som svarer på spørsmålet. Hvis den nevner tun0 og pakkene fortsatt dør, gå til tunnelens MTU og gatewayens IPv6-videresending i stedet for tilbake til telefonen.
Hvorfor det å legge til ::/0 vanligvis gjør det verre
Å legge til ::/0 endrer tunnelens krav fra ett prefiks til hver IPv6-destinasjon. På telefonen kan det tilfredsstille en rekkeviddetest, fordi en testadresse utenfor prefikset ditt nå ser rutbar ut. Det skaper ikke IPv6-oppstrømskapasitet på gatewayen, og mange hjemmegatewayer har ingen fungerende IPv6-oppstrømsforbindelse i det hele tatt. Resultatet er et svart hull for offentlig IPv6: navn som før falt tilbake til IPv4 henger nå, og den private siden kan se bedre ut bare fordi testen måler noe annet.
Det er også en politikostnad. Med ::/0 i tunnelen går all IPv6-trafikk ut gjennom VPN-et, også trafikk netteieren aldri har samtykket i å bære. Behandle det som en utrullingsbeslutning med en navngitt eier, ikke som et feilsøkingstrinn du tar klokken 1 om natten.
Arbeidsrekkefølgen som avslutter dette
Bekreft at AAAA-svaret kommer fra resolveren som eier sonen, les VpnService- og netd-tilstand for tun-grensesnittet, ta opp et net-export-spor for å se om Chromium droppet kandidaten, og test deretter turen frem og tilbake med ip -6 route get. Rett laget som faktisk feilet, og la splittpolitikken være. Hvis private navn trenger andre svar enn offentlige, er det nettopp det split tunneling er til.
Noter telefonens build, nettleserens versjon og resolveren du spurte. De tre fakta gjør "IPv6 is broken" til noe neste person kan reprodusere.