Routa värdens trafik genom en VPN i en VM: sex kontroller
Sex kontroller i ordning för att göra en VM till den VPN-gateway som dess egen värd routar genom: adapterläge, vidarebefordran, NAT, värdrutter, DNS, MTU.
Sex kontroller, körda i ordning, avgör om en VM kan fungera som VPN-gateway för sin egen värd. Hypervisorn gör inget av detta åt dig: gästen äger tunneln, värden äger en rutt, och nätet mellan dem är vanlig routning. Jag håller mig till listan eftersom ett överhoppat steg alltid ger samma symptom, tystnad, där värden glatt pingar gästen och inte når något internt.
Börja med orsaken. Antingen installeras företagsklienten bara inne i gästen, eller så håller policyn den där, och du behöver fortfarande den interna byggservern från värden. Om värden får ha sin egen klient, gör det i stället: en tunnel på värden slår varje gång två nätverk plus en NAT.
Kontroll 1: värden behöver en länk den kan adressera
Värden måste äga ett gränssnitt i samma prefix som gästens andra adapter. Host-only i VirtualBox, host-only eller ett eget VMnet i VMware Workstation, en intern brygga eller tap-enhet i QEMU/KVM och en Internal-switch i Hyper-V kvalar alla in. Gäst 192.168.56.2, värd 192.168.56.1, prefix 192.168.56.0/24 är upplägget jag använder i labb.
QEMU-nätverk i användarläge (-netdev user, standard-SLIRP-backenden) och VirtualBox NAT faller helt på den här kontrollen. Gästens paket når en proxyprocess på värden, så värden ser aldrig en enhet som bär gästens adresser och har inget att peka en rutt mot. Hyper-Vs Default Switch är samma historia. Om ping 192.168.56.2 från värden misslyckas, stanna: ingen rutt som läggs till senare reparerar det.
Kontroll 2: gästen vidarebefordrar och översätter
Paket från värden kommer in med en host-only källadress och en intern destination, så gästen måste vidarebefordra dem och sedan gömma dem bakom sin tunneladress. På en Linux-gäst betyder det vidarebefordran, ett FORWARD accept-par och source NAT mot tunneln:
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
MASQUERADE-regeln är den del folk utelämnar. Företagsroutrar vet sällan att 192.168.56.0/24 finns; med regeln ser interna servrar gästens tunneladress och svarar på den, och svaret hittar vägen tillbaka till gästen.
En Windows-gäst är klumpigare. IPEnableRouter=1 under SYSTEM\CurrentControlSet\Services\Tcpip\Parameters slår på vidarebefordran utan översättning, så det fungerar bara där företagsroutningen redan pekar tillbaka på ditt host-only-prefix. Internet Connection Sharing översätter, men numrerar om den delade adaptern till 192.168.137.1, så läs adressen den faktiskt tog innan du skriver värdrutter.
Kontroll 3: värdrutterna namnger gästen, inte tunneln
Skicka bara de prefix värden behöver genom gästen. På Linux räcker en rutt per prefix och den vänder rent tillbaka:
sudo ip route add 10.20.0.0/16 via 192.168.56.2
ip route get 10.20.30.40
På Windows är motsvarigheten route add 10.20.0.0 mask 255.255.0.0 192.168.56.2. Utelämna -p medan du fortfarande testar, så att en dålig rutt dör vid omstart, och lägg till det när vägen fungerar. Ta inte bort värdens standardrutt om inte varje program på värden ska använda tunneln; om full tunnel verkligen är kravet, lägg till de två /1-rutterna och behåll den direkta rutten till hypervisorns nät:
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
På en Windows-värd, kontrollera även gränssnittsmetriken. En rutt som lades till medan host-only-adaptern var inaktiverad stannar i tabellen men bär aldrig trafik, och en andra adapter med lägre metrik kan vinna sökningen efter samma prefix.
Kontroll 4: DNS följer rutten, inte tunnelns standard
Rutter flyttar paket; resolvern avgör vilka namn som skapar paket. Begränsa företagsresolvern till företagszonen i stället för att ersätta värdens resolver, och peka den mot en DNS-server som den nya rutten redan når. Med systemd-resolved på värden:
resolvectl dns eth1 10.20.0.53
resolvectl domain eth1 '~corp.example.com'
På Windows gör en post i namnupplösningspolicytabellen samma nytta: Add-DnsClientNrptRule -Namespace ".corp.example.com" -NameServers 10.20.0.53. Om gästen kör sin egen resolver på host-only-adressen, använd den adressen i stället, men först efter att ha bekräftat att den svarar på 192.168.56.2 och inte på loopback.
Kontrollera sedan MTU innan du skyller DNS för långsamma sidor. Tunnelns gränssnitt är mindre än värdens 1500-byte-gränssnitt, så en värd som skickar fullstora segment med DF-biten satt ser dem tappas någonstans inne i gästen. Det klassiska symptomet är en fungerande ping och en intern webbapp som hakar upp sig efter TLS-handskakningen. Strama åt MSS på vidarebefordransvägen i gästen:
sudo iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
Kontroll 5: verifiera från båda ändar
Från värden bör traceroute eller tracert mot en intern adress visa 192.168.56.2 som första hopp, inte den fysiska gatewayen. I gästen ser du samma försök gå ut: tcpdump -ni any host 10.20.30.40 visar den vidarebefordrade förfrågan på host-only-sidan och den översatta på tunneln. En förfrågan som går ut, kommer tillbaka och ändå lämnar värden tyst pekar på returvägen.
Två fel förklarar det mesta. Antingen bär gästens tunnel ingen returrutt för host-only-prefixet eftersom NAT-regeln saknas, eller så pekar värdrutten på en adress som gästen inte längre har efter en omstart. Läs adresserna igen med ip -br addr och ip route get i stället för att lita på anteckningar från förra sessionen.
Kontroll 6: gör det robust mot omstart och hypervisoruppgradering
Gör båda halvorna varaktiga: netplan- eller NetworkManager-ruttkonfiguration på värden, route add ... -p på Windows, och net.ipv4.ip_forward=1 i /etc/sysctl.d/ plus en uppsättning brandväggsregler som laddas om i gästen. Ta en snapshot av gästen när konfigurationen är verifierad, innan nästa företagsklientuppdatering kommer.
Host-only-nät numreras om när en hypervisor återskapar sina adaptrar, vilket tyst ogiltiggör varje rutt och NAT-regel byggd på 192.168.56.0/24. Efter en uppgradering, kör om de tre första kontrollerna i ordning; det tar en minut och fångar fallet där värden fortfarande har sin rutt medan gästen har flyttat till ett nytt subnät.
IPv6 behöver sin egen omgång. ip6tables-regler, AAAA-poster och en andra värdruttfamilj följer inte IPv4-uppsättningen, och en företagstjänst som nås över IPv6 kommer att se permanent trasig ut medan IPv4 fungerar.
Godkänd eller inte, i ordning: värden kan pinga gästens host-only-adress; gästen vidarebefordrar och gör MASQUERADE mot tunneln; ip route get returnerar gästen som gateway för det interna prefixet; företagsnamn löses genom den begränsade resolvern; traceroute visar gästen först; och samma sex svar överlever en omstart.