Zes controles, in volgorde uitgevoerd, bepalen of een VM als VPN-gateway voor zijn eigen host kan dienen. De hypervisor doet hier niets van voor je: de gast bezit de tunnel, de host bezit een route, en het netwerk ertussen is gewoon routering. Ik houd de lijst aan omdat het overslaan van één stap altijd hetzelfde symptoom geeft, stilte, waarbij de host de gast vrolijk pingt en niets intern bereikt.

Begin bij de reden. Ofwel de bedrijfsclient wordt alleen in de gast geïnstalleerd, ofwel het beleid houdt hem daar, en je hebt nog steeds de interne buildserver vanaf de host nodig. Als de host zijn eigen client mag hebben, doe dat dan: één tunnel op de host wint altijd van twee netwerken plus een NAT.

Controle 1: de host heeft een koppeling nodig die hij kan adresseren

De host moet een interface hebben in hetzelfde prefix als de tweede adapter van de gast. Host-only in VirtualBox, host-only of een eigen VMnet in VMware Workstation, een interne bridge of tap-apparaat in QEMU/KVM en een Internal-switch in Hyper-V komen allemaal in aanmerking. Gast 192.168.56.2, host 192.168.56.1, prefix 192.168.56.0/24 is de indeling die ik in labs gebruik.

QEMU-netwerken in gebruikersmodus (-netdev user, de standaard SLIRP-backend) en VirtualBox NAT falen deze controle volledig. Gastpakketten bereiken een proxyproces op de host, dus de host ziet nooit een apparaat dat de adressen van de gast draagt en heeft niets om een route naar te wijzen. De Default Switch van Hyper-V is hetzelfde verhaal. Als ping 192.168.56.2 vanaf de host faalt, stop dan: geen enkele later toegevoegde route herstelt dat.

Controle 2: de gast stuurt door en vertaalt

Pakketten van de host komen binnen met een host-only bronadres en een interne bestemming, dus de gast moet ze doorsturen en dan achter zijn tunneladres verbergen. Op een Linux-gast betekent dat doorsturen, een FORWARD accept-paar en source NAT richting de 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

De MASQUERADE-regel is het deel dat mensen weglaten. Bedrijfsrouters weten zelden dat 192.168.56.0/24 bestaat; met de regel zien interne servers het tunneladres van de gast en antwoorden daarop, en het antwoord vindt de weg terug naar de gast.

Een Windows-gast is onhandiger. IPEnableRouter=1 onder SYSTEM\CurrentControlSet\Services\Tcpip\Parameters schakelt doorsturen in zonder vertaling, dus het werkt alleen waar bedrijfsroutering al terugwijst naar jouw host-only prefix. Internet Connection Sharing vertaalt wel, maar hernummert de gedeelde adapter naar 192.168.137.1, dus lees het adres dat hij werkelijk heeft gekregen voordat je hostroutes schrijft.

Controle 3: hostroutes noemen de gast, niet de tunnel

Stuur alleen de prefixen door de gast die de host nodig heeft. Op Linux is één route per prefix genoeg en die draait netjes terug:

sudo ip route add 10.20.0.0/16 via 192.168.56.2
ip route get 10.20.30.40

Op Windows is het equivalent route add 10.20.0.0 mask 255.255.0.0 192.168.56.2. Laat -p weg terwijl je nog test, zodat een slechte route bij het herstarten sterft, en voeg het toe zodra het pad werkt. Verwijder de standaardroute van de host niet, tenzij elke toepassing op de host de tunnel moet gebruiken; als volledige tunnel echt de eis is, voeg dan de twee /1-routes toe en houd de directe route naar het hypervisornetwerk:

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

Controleer op een Windows-host ook de interfacemetriek. Een route die is toegevoegd terwijl de host-only-adapter was uitgeschakeld, blijft in de tabel staan maar draagt nooit verkeer, en een tweede adapter met een lagere metriek kan de opzoeking voor hetzelfde prefix winnen.

Controle 4: DNS volgt de route, niet de standaard van de tunnel

Routes verplaatsen pakketten; de resolver bepaalt welke namen pakketten opleveren. Beperk de bedrijfsresolver tot de bedrijfszone in plaats van de resolver van de host te vervangen, en wijs hem naar een DNS-server die de nieuwe route al bereikt. Met systemd-resolved op de host:

resolvectl dns eth1 10.20.0.53
resolvectl domain eth1 '~corp.example.com'

Op Windows doet een regel in de naamoplossingsbeleidstabel hetzelfde werk: Add-DnsClientNrptRule -Namespace ".corp.example.com" -NameServers 10.20.0.53. Als de gast zijn eigen resolver op het host-only-adres draait, gebruik dan dat adres, maar pas nadat je hebt bevestigd dat hij op 192.168.56.2 antwoordt en niet op loopback.

Controleer daarna de MTU voordat je DNS de schuld geeft van trage pagina's. De tunnelinterface is kleiner dan de 1500-byte-interface van de host, dus een host die segmenten op volle grootte met de DF-bit verzendt, ziet ze ergens in de gast worden weggegooid. Het klassieke symptoom is een werkende ping en een interne webapp die na de TLS-handshake blijft hangen. Knel de MSS op het doorstuurpad van de gast:

sudo iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

Controle 5: verifieer van beide kanten

Vanaf de host zou traceroute of tracert naar een intern adres 192.168.56.2 als eerste hop moeten tonen, niet de fysieke gateway. In de gast zie je dezelfde poging vertrekken: tcpdump -ni any host 10.20.30.40 toont het doorgestuurde verzoek aan de host-only kant en het vertaalde op de tunnel. Een verzoek dat eruit gaat, terugkomt en de host toch stil laat, wijst op het terugpad.

Twee fouten verklaren het meeste daarvan. Ofwel de tunnel van de gast draagt geen terugroute voor het host-only prefix omdat de NAT-regel ontbreekt, ofwel de hostroute wijst naar een adres dat de gast na een herstart niet meer heeft. Lees de adressen opnieuw met ip -br addr en ip route get in plaats van notities van de vorige sessie te vertrouwen.

Controle 6: laat het een herstart en een hypervisor-upgrade overleven

Maak beide helften permanent: netplan- of NetworkManager-routeconfiguratie op de host, route add ... -p op Windows, en net.ipv4.ip_forward=1 in /etc/sysctl.d/ plus een set firewallregels die in de gast opnieuw wordt geladen. Maak een snapshot van de gast zodra de configuratie is geverifieerd, voordat de volgende bedrijfsclient-update komt.

Host-only-netwerken worden hernummerd wanneer een hypervisor zijn adapters opnieuw aanmaakt, wat elke route en NAT-regel die op 192.168.56.0/24 is gebouwd stil ongeldig maakt. Herhaal na een upgrade de eerste drie controles op volgorde; dat kost een minuut en vangt het geval waarin de host zijn route nog heeft terwijl de gast naar een nieuw subnet is verhuisd.

IPv6 vraagt een eigen ronde. ip6tables-regels, AAAA-records en een tweede hostroute-familie volgen de IPv4-instelling niet, en een bedrijfsdienst die via IPv6 bereikbaar is, zal permanent kapot lijken terwijl IPv4 werkt.

Geslaagd of niet, op volgorde: de host kan het host-only-adres van de gast pingen; de gast stuurt door en doet MASQUERADE richting tunnel; ip route get geeft de gast terug als gateway voor het interne prefix; bedrijfsnamen worden opgelost via de beperkte resolver; traceroute toont de gast eerst; en dezelfde zes antwoorden overleven een herstart.

Gerelateerde artikelen