Android-VPN werkt met IPv6, maar de browser kiest nog steeds IPv4
Volg de vier fasen waarin een privé-IPv6-adres verdwijnt: de resolver, de VpnService-verklaring, de kandidaatcontrole van de browser en de aflevering van de route.
De VPN staat aan, de privé-webinterface antwoordt over IPv6 vanaf een laptop, en de Android-telefoon opent dezelfde pagina nog steeds over IPv4 of weigert hem helemaal te laden. Het AAAA-record bestaat. De tunnel meldt een IPv6-adres. Niets in de client ziet er verkeerd uit. Vier afzonderlijke beslissingen bepalen de uitkomst: welke resolver antwoordde, wat de VpnService aan Android verklaarde, welke adresfamilie de browser wilde proberen en of een pakket de reis heen en terug kan maken. Werk ze in die volgorde af in plaats van een standaardroute toe te voegen en te hopen dat het symptoom verschuift.
Stap 1: bewijs welke resolver de AAAA-query beantwoordde
Android heeft niet één DNS-pad. Een VPN kan een DNS-server voor zijn netwerk pushen, het systeem kan Private DNS gebruiken voor hostnamen die het geschikt acht, en Chrome kan zijn eigen versleutelde resolver draaien vanaf chrome://settings/security. Op een telefoon waar de tunnel 10.61.0.1 pusht maar Private DNS naar een publieke provider wijst, wordt de naam in je privézone niet opgelost door de machine die de zone bezit. De browser krijgt een antwoord van een resolver zonder bevoegdheid over die naam en behandelt het als ontbrekend, en de fouttekst noemt DNS nooit.
Vraag het de resolver van de tunnel rechtstreeks voordat je iets anders verandert. De eerste twee commando's tonen welke DNS-servers Android aan het actieve netwerk heeft gekoppeld en of Private DNS in automatische of strikte modus staat; de derde draait vanaf elke client in de tunnel, niet vanaf de telefoon.
adb shell dumpsys connectivity | grep -A3 "DnsAddresses"
adb shell settings get global private_dns_mode
nslookup -type=AAAA nas.lan 10.61.0.1
Stap 2: lees wat de VpnService werkelijk heeft verklaard
De Android-kant is expliciet en niet afgeleid. Een VpnService.Builder voegt adressen toe met addAddress, routes met addRoute, DNS-servers met addDnsServer, en kan de hele tunnel met allowFamily tot één adresfamilie beperken. Een builder die allowFamily(AF_INET) aanriep en later een IPv6-route toevoegde, heeft het systeem twee tegenstrijdige dingen verteld, en de gezinsbeperking is wat het systeem vasthoudt. Een route die fd00:61::/64 dekt in combinatie met een interfaceadres in een ander prefix mislukt om een vergelijkbare reden: het adres bestaat, maar het is niet on-link voor die route.
Lees de verklaring in plaats van de schakelaar in de app te vertrouwen. dumpsys netd drukt de adressen en routes af die aan de tun-interface zijn gekoppeld, en de per-netwerk LinkProperties in dumpsys connectivity toont de DNS-lijst naast de families die het netwerk claimt.
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"
Als de tun-interface een IPv6-adres heeft maar geen enkele route bij het prefix van de dienst past, is de IPv6-aflevering al stuk voordat er een browser aan te pas komt. Dat is een andere bug dan een browser die weigert te proberen, en die vraagt om een andere oplossing.
Stap 3: de browser beslist of hij IPv6 überhaupt probeert
Chromium gebruikt niet elk AAAA-record dat het ontvangt. De hostresolver heeft IPv6-bereikbaarheidstests en kandidatenfiltering die IPv6 kunnen laten vallen of lager prioriteren wanneer het netwerk wordt geacht het niet te kunnen dragen, en de broncode van de resolver toont die test samen met de voorwaarden eromheen. De logica hangt af van versie en flags, en dat is precies waarom twee telefoons op dezelfde tunnel zich anders kunnen gedragen. Zodra er kandidaten zijn, laat Happy Eyeballs de families per verbinding racen, dus een IPv6-pad dat langzaam antwoordt kan nog steeds verliezen van IPv4 dat snel antwoordt.
Observeer de beslissing in plaats van haar af te leiden. Een sessie die via chrome://net-export is opgenomen en in de netlog-viewer wordt afgespeeld, toont elke resolutie en de gekozen familie; chrome://net-internals/#dns toont de gecachte resultaten. Een resolutie die alleen A-records teruggeeft voor een naam die AAAA heeft bij je eigen resolver, wijst rechtstreeks naar deze fase.
Stap 4: verifieer dat een pakket de reis heen en terug kan maken
Adresselectie is geen aflevering. Android houdt per netwerk routetabellen en policyregels bij die een tabel op fwmark kiezen, dus een route die in de hoofdtabel zichtbaar is, is niet automatisch de route die een socket gebruikt. Regels lezen en de kernel vragen een bestemming voor een bronadres op te lossen, scheidt die twee.
adb shell ip -6 rule show
adb shell ip -6 route get fd00:61::20 from fd00:61::10
De uitvoer van route get is degene die de vraag beantwoordt. Noemt die tun0 en sterven pakketten nog steeds, ga dan naar de MTU van de tunnel en het IPv6-doorsturen van de gateway in plaats van terug naar de telefoon.
Waarom ::/0 toevoegen het meestal erger maakt
::/0 toevoegen verandert de claim van de tunnel van één prefix naar elke IPv6-bestemming. Op de telefoon kan dat een bereikbaarheidstest vervullen, omdat een testadres buiten je prefix nu routeerbaar lijkt. Het creëert geen IPv6-upstreamcapaciteit op de gateway, en veel thuisgateways hebben helemaal geen werkende IPv6-uplink. Het resultaat is een zwart gat voor publieke IPv6: namen die vroeger terugvielen op IPv4 blijven nu hangen, en de privépagina lijkt misschien beter alleen omdat de test iets anders meet.
Er is ook een beleidskostenpost. Met ::/0 in de tunnel verlaat al het IPv6-verkeer het netwerk via de VPN, inclusief verkeer dat de netwerkeigenaar nooit heeft ingestemd te dragen. Behandel dat als een uitrolbeslissing met een genoemde eigenaar, niet als een debugstap die je om 1 uur 's nachts neemt.
De werkvolgorde die dit beëindigt
Bevestig dat het AAAA-antwoord van de resolver komt die de zone bezit, lees de VpnService- en netd-status voor de tun-interface, leg een net-export-trace vast om te zien of Chromium de kandidaat liet vallen, en test daarna de reis heen en terug met ip -6 route get. Repareer de laag die werkelijk faalde en laat het splitbeleid met rust. Als privénamen andere antwoorden nodig hebben dan publieke, is dat precies waar split tunneling voor is.
Noteer de build van de telefoon, de browserversie en de resolver die je hebt bevraagd. Die drie feiten maken van "IPv6 is broken" iets wat de volgende persoon kan reproduceren.