Android-Emulator und Host-VPN: DNS-Snapshot und NAT erklärt
Der Gast sitzt hinter dem NAT des Emulators und behält die beim Start kopierte DNS-Liste. Richten Sie den Tunnel vor dem Start ein und testen Sie dann die Auflösung aus dem Gast heraus.
Wenn der Emulator einen Build-Server nicht erreicht, den der Browser des Hosts problemlos öffnet, lautet die nützliche Frage nicht, ob das VPN funktioniert. Sie lautet, welcher von zwei Mechanismen dem Gast fehlt. Das virtuelle Gerät betreibt einen eigenen Netzwerk-Stack hinter dem NAT des Emulators, und seine Resolver-Liste ist eine beim Start erstellte Kopie, sodass ein später aufgebauter Tunnel den Pfad des Hosts ändert, ohne zu ändern, was der Gast fragt. Das Verständnis dieser beiden Schichten erklärt nahezu jede Variante dieses Problems.
Der Gast ist ein eigener Stack hinter einem festen NAT
Das QEMU-Netzwerk im Benutzermodus legt den Gast auf 10.0.2.15, das Gateway auf 10.0.2.2 und den DNS-Dienst auf 10.0.2.3 bis 10.0.2.6. Ausgehender Gastverkehr wird nicht vom Host-Kernel weitergeleitet; er wird in Sockets auf der Hostseite übersetzt, einen pro Gastverbindung, und diese Sockets verlassen den Adressraum des Hosts. Deshalb erbt eine Gastverbindung die Routing-Entscheidung des Hosts in dem Moment, in dem sie entsteht, und deshalb hat der Gast keinen Eintrag in der Routing-Tabelle, der Ihren Tunnel nennt.
Derselbe Mechanismus gibt dem Gast einen nützlichen Ausweg. 10.0.2.2 ist ein Alias für die Loopback-Schnittstelle des Hosts, sodass ein Dienst, der auf dem Laptop auf 127.0.0.1 lauscht, vom Gast unter dieser Adresse erreichbar ist. Alles, was der Client nur auf Loopback bereitstellt, ist so erreichbar, und das ist die Grundlage der weiter unten beschriebenen Proxy-Anordnung.
Was der Gast nicht kann, ist, das Hostnetz zu beobachten, als wäre es ein Namespace darauf. Es gibt keine Bridge, keine gemeinsame Routing-Tabelle und keinen geerbten Resolver, nur den NAT-Dienst, der seine Pakete annimmt, und den Snapshot, den der Starter beim Start des virtuellen Geräts aufgenommen hat.
DNS ist ein Snapshot, keine Live-Ansicht
Beim Start liest der Emulator die Resolver-Liste des Hosts und übergibt dem Gast bis zu vier Server, bereitgestellt unter den Adressen 10.0.2.3 bis 10.0.2.6. War der Tunnel zu diesem Zeitpunkt unten, enthält der Snapshot den öffentlichen Resolver, den der Laptop nutzte, und der Gast fragt ihn für den Rest seines Lebens. Öffentliche Namen werden aufgelöst, interne scheitern, und jedes Symptom zeigt auf das VPN, während der tatsächliche veraltete Wert eine Resolver-Liste ist, die Minuten vor dem Aufbau des Tunnels erfasst wurde.
Die Korrektur über die Reihenfolge ist also kein Aberglaube. Stellen Sie zuerst den Tunnel her, starten Sie dann den Emulator neu, und bevorzugen Sie einen Kaltstart gegenüber der Wiederherstellung eines Snapshots, weil ein Schnellstart-Image mit dem zuvor gespeicherten Resolver- und Routing-Zustand zurückkehren kann. Wenn Sie sehen wollen, was der Gast aktuell verwendet, fragen Sie das Gerät statt den Host:
adb shell dumpsys connectivity | grep -i -A2 dns
adb shell ping -c 1 build.internal.exampleDer Emulator akzeptiert beim Start auch einen expliziten Resolver, was nützlich ist, wenn Sie genau wissen, welchen Server der Gast verwenden soll, und gefährlich, wenn dieser Server öffentlich ist:
emulator -avd Pixel_API_34 -dns-server 203.0.113.53Ein öffentlicher Resolver hat keine Kopie einer internen Zone, sodass das Festnageln eines solchen ein Reihenfolgeproblem in einen dauerhaften Fehler verwandelt. Wenn das Profil privates DNS erzwingt, lassen Sie es den Tunnel liefern und starten Sie den Gast kalt, statt eine Adresse fest zu verdrahten.
Routing folgt dem Host zum Zeitpunkt der Verbindung
Da Gastverbindungen zu Host-Sockets werden, wird die Routing-Entscheidung beim Anlegen des Sockets getroffen. Tunnel vor der Anfrage bedeutet, dass die Anfrage gemäß den Profilrouten durch den Tunnel geht. Ein Split-Tunnel-Profil, das nur ausgewählte Präfixe führt, lässt Ihr privates Subnetz bereitwillig draußen, sodass die Erreichbarkeit des Hosts eine Hypothese über den Gast ist, kein Ergebnis. Bestehende Gastverbindungen behalten den Pfad, mit dem sie erstellt wurden, weshalb ein Client, der sich neu verbindet, einen hängenden Download im Emulator nicht immer repariert.
Die Prüfung gehört auf die Host-Schnittstelle, nicht in die Statistik des Gasts:
sudo tcpdump -ni tun0 'host 203.0.113.10'Erscheint die Anfrage des Gasts auf der Tunnel-Schnittstelle, funktioniert das Routing, und das Problem liegt darüber. Erscheint sie auf der physischen Schnittstelle, deckt das Profil dieses Präfix nicht ab, und keine Umkonfiguration auf der Gastseite ändert das.
Wenn der Client nur einen Loopback-Proxy anbietet
Manche kommerziellen Clients erzeugen gar keinen Systemtunnel. Sie stellen einen HTTP- oder SOCKS-Listener auf 127.0.0.1 bereit und erwarten, dass Anwendungen ihn nutzen. Der Gast kann diesen Socket nicht direkt sehen, aber dem Emulator kann gesagt werden, ihn zu verwenden, entweder über die erweiterten Steuerelemente (Einstellungen, dann Proxy, manueller Modus, Host 127.0.0.1 und der vom Client ausgegebene Port) oder beim Start:
emulator -avd Pixel_API_34 -http-proxy http://127.0.0.1:8080Kopieren Sie den Port aus dem Client-Fenster; ein geratener Port scheitert still und sieht wie ein defekter Tunnel aus. Bedenken Sie, was das abdeckt: Eine HTTP-Proxy-Einstellung wird von proxybewussten Anwendungen beachtet, und rohe Sockets ignorieren sie völlig. Wenn die Arbeitslast ein natives Binärprogramm ist, das seine eigenen Verbindungen öffnet, ist der Proxy-Pfad nicht gleichwertig mit einem Tunnel, und der Vergleich muss ausdrücklich erfolgen.
Beweisen Sie das Ergebnis aus dem Gast heraus
Trennen Sie Auflösung und Routing mit zwei Tests in derselben Sitzung. Ein Name, der scheitert, während die numerische Adresse antwortet, ist ein DNS-Snapshot-Problem, und die Lösung ist die Reihenfolge oder ein expliziter Resolver. Scheitern beide, deutet das auf Routing oder Richtlinie hin, und die nächste Prüfung ist, ob die App in einem Arbeitsprofil mit eigenen Netzwerkbeschränkungen läuft.
Wissen Sie schließlich, auf welchem Gast Sie testen. Sehr alte Emulator-Images wurden ohne die tun-Unterstützung ausgeliefert, die ein VPN-Client auf der Gastseite benötigt, sodass dort kein Profil funktionieren konnte; aktuelle Images enthalten sie. Ein Client, der auf einem aktuellen Image scheitert, ist ein Client- oder Profilproblem, und der Neuaufbau des Host-Tunnels ändert das Ergebnis nicht.