Når emulatoren ikke når en byggeserver som nettleseren på vertsmaskinen åpner helt fint, er det nyttige spørsmålet ikke om VPN-en virker. Spørsmålet er hvilken av to mekanismer gjesten mangler. Den virtuelle enheten kjører sin egen nettverksstack bak emulatorens NAT, og resolverlisten dens er en kopi tatt ved oppstart, så en tunnel som kommer opp etterpå endrer vertens rute uten å endre det gjesten spør om. Å forstå disse to lagene forklarer nesten alle varianter av problemet.

Gjesten er en egen stack bak en fast NAT

QEMU sitt brukermodusnettverk plasserer gjesten på 10.0.2.15 med gateway på 10.0.2.2, og DNS-tjenesten på 10.0.2.3 til 10.0.2.6. Utgående trafikk fra gjesten videresendes ikke av vertens kjerne; den oversettes til sockets på vertssiden, én per tilkobling fra gjesten, og disse socketene går ut fra vertens adresserom. Derfor arver en gjestetilkobling vertens rutingsbeslutning i det øyeblikket den opprettes, og derfor har gjesten ingen oppføring i rutetabellen som navngir tunnelen din.

Samme mekanisme gir gjesten en nyttig nødutgang. 10.0.2.2 er et alias for vertens loopback-grensesnitt, så en tjeneste som lytter på 127.0.0.1 på laptopen er tilgjengelig fra gjesten på den adressen. Alt klienten bare eksponerer på loopback kan nås den veien, og det er grunnlaget for proxyoppsettet som beskrives lenger ned.

Det gjesten ikke kan, er å observere vertens nettverk som om det var dens eget namespace. Det finnes ingen bro, ingen delt rutetabell og ingen arvet resolver, bare NAT-tjenesten som tar imot pakkene og snapshottet som oppstarteren tok da den virtuelle enheten startet.

DNS er et snapshot, ikke et levende bilde

Ved oppstart leser emulatoren vertens resolverliste og gir gjesten opptil fire servere, eksponert på adressene 10.0.2.3 til 10.0.2.6. Hvis tunnelen var nede i det øyeblikket, inneholder snapshottet den offentlige resolveren laptopen brukte, og gjesten fortsetter å spørre den resten av livet. Offentlige navn løses, interne navn feiler, og alle symptomer peker på VPN-en mens den egentlige utdaterte verdien er en resolverliste fanget noen minutter før tunnelen kom opp.

Rekkefølgerettelsen er derfor ikke folketro. Koble til tunnelen først, start deretter emulatoren på nytt, og foretrekk kald oppstart framfor gjenoppretting av et snapshot, fordi et hurtigoppstartsbilde kan komme tilbake med resolver- og rutetilstanden det lagret tidligere. Hvis du vil se hva gjesten bruker nå, spør enheten og ikke verten:

adb shell dumpsys connectivity | grep -i -A2 dns
adb shell ping -c 1 build.internal.example

Emulatoren godtar også en eksplisitt resolver ved oppstart, noe som er nyttig når du vet nøyaktig hvilken server gjesten skal bruke, og farlig når den serveren er offentlig:

emulator -avd Pixel_API_34 -dns-server 203.0.113.53

En offentlig resolver har ingen kopi av en intern sone, så å låse én gjør et rekkefølgeproblem om til en permanent feil. Hvis profilen skyver privat DNS, la tunnelen levere den og kaldstart gjesten i stedet for å hardkode en adresse.

Ruting følger verten ved tilkoblingstidspunktet

Fordi gjestetilkoblinger blir sockets på verten, tas rutingsbeslutningen når socketen opprettes. Tunnel oppe før forespørselen betyr at forespørselen går ut gjennom tunnelen, underlagt profilens ruter. En splitt-tunnel-profil som bare bærer utvalgte prefikser lar ditt private subnett bli stående utenfor, så vertens nåbarhet er en hypotese om gjesten, ikke et resultat. Eksisterende gjestetilkoblinger beholder ruten de ble opprettet med, og derfor fikser ikke en klient som kobler til på nytt alltid en nedlasting som henger i emulatoren.

Verifiseringen hører hjemme på vertens grensesnitt, ikke i gjestens statistikk:

sudo tcpdump -ni tun0 'host 203.0.113.10'

Hvis gjestens forespørsel dukker opp på tunellgrensesnittet, virker rutingen og problemet ligger over den. Hvis den dukker opp på det fysiske grensesnittet, dekker ikke profilen det prefikset, og ingen omkonfigurering på gjestesiden vil endre det.

Når klienten bare tilbyr en loopback-proxy

Noen kommersielle klienter lager ingen systemtunnel i det hele tatt. De eksponerer en HTTP- eller SOCKS-lytter på 127.0.0.1 og forventer at applikasjonene bruker den. Gjesten kan ikke se den socketen direkte, men emulatoren kan bli bedt om å bruke den, enten gjennom de utvidede kontrollene (Settings, deretter Proxy, manuell modus, vert 127.0.0.1 og porten klienten skriver ut) eller ved oppstart:

emulator -avd Pixel_API_34 -http-proxy http://127.0.0.1:8080

Kopier porten fra klientvinduet; en gjettet port feiler lydløst og ser ut som en ødelagt tunnel. Husk hva dette dekker: en HTTP-proxyinnstilling respekteres av applikasjoner som kjenner proxy, og rå sockets ignorerer den helt. Hvis arbeidslasten er en native binærfil som åpner sine egne tilkoblinger, er proxyveien ikke likeverdig med en tunnel, og sammenligningen må gjøres eksplisitt.

Bevis resultatet fra gjestens innside

Skill oppslag fra ruting med to tester i samme økt. Et navn som feiler mens den numeriske adressen svarer, er et DNS-snapshot-problem, og løsningen er rekkefølge eller en eksplisitt resolver. Feiler begge, peker det på ruting eller policy, og neste sjekk er om appen kjører i en arbeidsprofil med egne nettverksbegrensninger.

Til slutt, vit hvilken gjest du tester på. Svært gamle emulatorbilder ble levert uten tun-støtten en VPN-klient på gjestesiden trenger, så ingen profil kunne noen gang virke der; dagens bilder har den. En klient som feiler på et dagsaktuelt bilde er et klient- eller profilproblem, og å bygge vertstunnelen på nytt endrer ikke resultatet.

Relaterte artikler