Host-Traffic durch ein VPN in einer VM routen: sechs Prüfungen
Sechs Prüfungen in Reihenfolge, um eine VM zum VPN-Gateway zu machen, über das ihr eigener Host routet: Adaptermodus, Weiterleitung, NAT, Host-Routen, DNS, MTU.
Sechs Prüfungen, in dieser Reihenfolge ausgeführt, entscheiden, ob eine VM als VPN-Gateway für ihren eigenen Host dienen kann. Der Hypervisor erledigt nichts davon für Sie: Der Gast besitzt den Tunnel, der Host besitzt eine Route, und das Netzwerk dazwischen ist gewöhnliches Routing. Ich halte die Liste ein, weil ein ausgelassener Schritt immer dasselbe Symptom erzeugt, Stille, bei der der Host den Gast fröhlich anpingt und nichts Internes erreicht.
Beginnen Sie mit dem Grund. Entweder lässt sich der Unternehmensclient nur im Gast installieren, oder die Richtlinie hält ihn dort, und Sie brauchen trotzdem den internen Build-Server vom Host. Wenn der Host seinen eigenen Client haben darf, tun Sie das stattdessen: ein Tunnel auf dem Host schlägt jedes Mal zwei Netzwerke plus ein NAT.
Prüfung 1: Der Host braucht eine Verbindung, die er adressieren kann
Der Host muss eine Schnittstelle besitzen, die im selben Präfix wie der zweite Adapter des Gasts liegt. Host-only in VirtualBox, Host-only oder ein eigenes VMnet in VMware Workstation, eine interne Bridge oder ein Tap-Gerät in QEMU/KVM und ein Internal-Switch in Hyper-V qualifizieren sich alle. Gast 192.168.56.2, Host 192.168.56.1, Präfix 192.168.56.0/24 ist das Layout, das ich in Laboren verwende.
QEMU-Netzwerk im Benutzermodus (-netdev user, der Standard-SLIRP-Backend) und VirtualBox-NAT fallen bei dieser Prüfung komplett durch. Gastpakete erreichen einen Proxy-Prozess auf dem Host, sodass der Host nie ein Gerät mit den Adressen des Gasts sieht und nichts hat, worauf er eine Route zeigen könnte. Der Default Switch von Hyper-V ist dieselbe Geschichte. Wenn ping 192.168.56.2 vom Host fehlschlägt, hören Sie auf: keine später hinzugefügte Route repariert das.
Prüfung 2: Der Gast leitet weiter und übersetzt
Pakete vom Host kommen mit einer Host-only-Quelladresse und einem internen Ziel an, also muss der Gast sie weiterleiten und dann hinter seiner Tunneladresse verstecken. Auf einem Linux-Gast bedeutet das Weiterleitung, ein FORWARD-accept-Paar und Source-NAT in Richtung Tunnel:
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -A FORWARD -i eth1 -o tun0 -j ACCEPT
sudo iptables -A FORWARD -i tun0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -t nat -A POSTROUTING -s 192.168.56.0/24 -o tun0 -j MASQUERADE
Die MASQUERADE-Regel ist der Teil, den Leute weglassen. Unternehmensrouter wissen selten, dass 192.168.56.0/24 existiert; mit der Regel sehen interne Server die Tunneladresse des Gasts und antworten darauf, und die Antwort findet den Weg zurück zum Gast.
Ein Windows-Gast ist ungeschickter. IPEnableRouter=1 unter SYSTEM\CurrentControlSet\Services\Tcpip\Parameters schaltet die Weiterleitung ohne Übersetzung ein, funktioniert also nur dort, wo das Unternehmensrouting bereits auf Ihr Host-only-Präfix zurückzeigt. Internet Connection Sharing übersetzt zwar, nummeriert den gemeinsam genutzten Adapter aber auf 192.168.137.1 um, also lesen Sie die Adresse, die er tatsächlich erhalten hat, bevor Sie Host-Routen schreiben.
Prüfung 3: Host-Routen nennen den Gast, nicht den Tunnel
Schicken Sie nur die Präfixe durch den Gast, die der Host braucht. Unter Linux reicht eine Route pro Präfix, und sie kehrt sauber zurück:
sudo ip route add 10.20.0.0/16 via 192.168.56.2
ip route get 10.20.30.40
Unter Windows ist das Gegenstück route add 10.20.0.0 mask 255.255.0.0 192.168.56.2. Lassen Sie -p weg, solange Sie noch testen, damit eine schlechte Route beim Neustart stirbt, und fügen Sie es hinzu, sobald der Pfad funktioniert. Entfernen Sie die Standardroute des Hosts nur, wenn jede Anwendung auf dem Host den Tunnel nutzen soll; wenn Full Tunnel wirklich die Anforderung ist, fügen Sie die beiden /1-Routen hinzu und behalten Sie die direkte Route zum Hypervisor-Netz:
sudo ip route add 0.0.0.0/1 via 192.168.56.2
sudo ip route add 128.0.0.0/1 via 192.168.56.2
Prüfen Sie auf einem Windows-Host auch die Schnittstellenmetrik. Eine Route, die hinzugefügt wurde, während der Host-only-Adapter deaktiviert war, bleibt in der Tabelle, trägt aber nie Verkehr, und ein zweiter Adapter mit niedrigerer Metrik kann die Suche für dasselbe Präfix gewinnen.
Prüfung 4: DNS folgt der Route, nicht dem Tunnel-Standard
Routen bewegen Pakete; der Resolver entscheidet, welche Namen Pakete erzeugen. Beschränken Sie den Unternehmens-Resolver auf die Unternehmenszone, statt den Resolver des Hosts zu ersetzen, und zeigen Sie ihn auf einen DNS-Server, den die neue Route bereits erreicht. Mit systemd-resolved auf dem Host:
resolvectl dns eth1 10.20.0.53
resolvectl domain eth1 '~corp.example.com'
Unter Windows erledigt ein Eintrag in der Namensauflösungs-Richtlinientabelle dasselbe: Add-DnsClientNrptRule -Namespace ".corp.example.com" -NameServers 10.20.0.53. Wenn der Gast seinen eigenen Resolver auf der Host-only-Adresse betreibt, verwenden Sie stattdessen diese Adresse, aber erst nachdem Sie bestätigt haben, dass er auf 192.168.56.2 und nicht auf Loopback antwortet.
Prüfen Sie dann die MTU, bevor Sie DNS langsame Seiten vorwerfen. Die Tunnelschnittstelle ist kleiner als die 1500-Byte-Schnittstelle des Hosts, sodass ein Host, der Segmente voller Größe mit gesetztem DF-Bit sendet, sie irgendwo im Gast verwerfen lässt. Das klassische Symptom ist ein funktionierendes ping und eine interne Web-App, die nach dem TLS-Handshake hängen bleibt. Begrenzen Sie MSS auf dem Weiterleitungspfad im Gast:
sudo iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
Prüfung 5: von beiden Enden verifizieren
Vom Host sollte traceroute oder tracert zu einer internen Adresse 192.168.56.2 als ersten Hop zeigen, nicht das physische Gateway. Im Gast beobachten Sie denselben Versuch beim Verlassen: tcpdump -ni any host 10.20.30.40 zeigt die weitergeleitete Anfrage auf der Host-only-Seite und die übersetzte auf dem Tunnel. Eine Anfrage, die hinausgeht, zurückkommt und den Host trotzdem stumm lässt, deutet auf den Rückweg hin.
Zwei Fehler erklären das meiste davon. Entweder trägt der Tunnel des Gasts keine Rückroute für das Host-only-Präfix, weil die NAT-Regel fehlt, oder die Host-Route zeigt auf eine Adresse, die der Gast nach einem Neustart nicht mehr hat. Lesen Sie die Adressen mit ip -br addr und ip route get erneut, statt Notizen aus der letzten Sitzung zu vertrauen.
Prüfung 6: Neustart und Hypervisor-Upgrade überstehen
Machen Sie beide Hälften dauerhaft: netplan- oder NetworkManager-Routenkonfiguration auf dem Host, route add ... -p unter Windows und net.ipv4.ip_forward=1 in /etc/sysctl.d/ plus ein Firewall-Regelsatz, der im Gast neu geladen wird. Erstellen Sie einen Snapshot des Gasts, sobald die Konfiguration verifiziert ist, bevor das nächste Unternehmensclient-Update eintrifft.
Host-only-Netze werden neu nummeriert, wenn ein Hypervisor seine Adapter neu erstellt, was jede Route und NAT-Regel, die auf 192.168.56.0/24 aufbaut, stillschweigend ungültig macht. Wiederholen Sie nach einem Upgrade die ersten drei Prüfungen in Reihenfolge; das kostet eine Minute und fängt den Fall ab, in dem der Host noch seine Route hat, während der Gast in ein neues Subnetz gewechselt ist.
IPv6 braucht einen eigenen Durchgang. ip6tables-Regeln, AAAA-Einträge und eine zweite Host-Routenfamilie folgen dem IPv4-Setup nicht, und ein über IPv6 erreichbarer Unternehmensdienst wird dauerhaft kaputt aussehen, während IPv4 funktioniert.
Bestanden oder nicht, in Reihenfolge: der Host kann die Host-only-Adresse des Gasts anpingen; der Gast leitet weiter und macht MASQUERADE Richtung Tunnel; ip route get liefert den Gast als Gateway für das interne Präfix; Unternehmensnamen werden über den begrenzten Resolver aufgelöst; traceroute zeigt den Gast zuerst; und dieselben sechs Antworten überleben einen Neustart.