Je dienst draait op de machine, de tunnel staat, en toch wacht de browser op je bureau nog steeds op antwoord. Niets is in de gebruikelijke zin stuk: de toepassing luistert binnen een netwerknaamruimte, en die stack is onzichtbaar voor het LAN. De loopback hoort bij de naamruimte, dus een client op een andere machine heeft geen adres dat de poort bereikt. Eén bewuste sprong, of één veth-paar, lost dat op zonder de rest van de host te verplaatsen.

Waarom niets op het LAN-adres antwoordt

Een naamruimte is een volledige netwerkstack: interfaces, routes, firewallregels en een privé-loopback. Een proces dat via ip netns exec start, ziet die stack en niets anders, dus het adres waaraan het bindt, wordt alleen binnen de naamruimte opgelost. De eigen 127.0.0.1 van de host is een heel andere loopback.

Daarom mislukt curl op de host terwijl dezelfde opdracht binnen de naamruimte slaagt. De toepassing is gezond; het adres bestaat simpelweg niet in de stack van de host.

Publiceer één poort met een socat-sprong

socat overbrugt de twee stacks in gebruikersruimte, wat genoeg is wanneer één TCP-poort moet oversteken. De hostzijde luistert op het LAN en start voor elke geaccepteerde verbinding een tweede socat binnen de naamruimte die verbinding maakt met de loopback van de app. Het binnenproces bereikt de toepassing precies zoals een lokale client dat zou doen. Aan de routering van de naamruimte verandert niets, dus de app blijft de tunnel als enige uitgang gebruiken.

socat TCP-LISTEN:9100,reuseaddr,fork EXEC:'ip netns exec vpn socat STDIO tcp-connect:127.0.0.1:9100',nofork

Het buitenproces heeft root of de mogelijkheid nodig om de naamruimte binnen te gaan. Als de VPN wegvalt, verliest de app zijn pad en faalt de gepubliceerde poort gesloten, en dat is het gedrag dat je van een gevangenis wilt.

Gebruik een veth-paar wanneer meer dan één poort oversteekt

Een veth-paar is het juiste antwoord wanneer meerdere poorten of protocollen moeten oversteken, of wanneer andere hosts verbindingen moeten starten. Het ene uiteinde blijft in de host, het andere verhuist naar de naamruimte, en een kleine /30 geeft beide kanten een stabiel adres. Een hostroute stuurt vervolgens het adres van de naamruimte over het paar.

ip link add veth0 type veth peer name veth1
ip link set veth1 netns vpn
ip addr add 10.77.0.1/30 dev veth0
ip link set veth0 up
ip netns exec vpn ip addr add 10.77.0.2/30 dev veth1
ip netns exec vpn ip link set veth1 up

Voeg geen standaardroute via de host toe tenzij je de gevangenis wilt doorbreken. De tunnel moet de uitgang blijven, dus via het paar is alleen het gepubliceerde serviceadres bereikbaar. Geef de naamruimte ook een eigen resolverbestand, want ip netns exec leest /etc/netns/vpn/resolv.conf en zonder dat is naamresolutie in de gevangenis leeg.

Test vanaf een andere machine, niet vanaf de host

Voer de test uit vanaf een tweede machine, want de host kan een lokale listener bereiken via paden die niets over het LAN zeggen. Controleer eerst waaraan de toepassing binnen de naamruimte werkelijk gebonden is, en verbind dan van buitenaf met het gepubliceerde adres. Binden aan elk adres daar verbreedt de gevangenis niet, want de wildcard hoort nog steeds bij de naamruimte en het LAN kan die niet zien.

ip netns exec vpn ss -lntp

Als de verbinding vanaf de host werkt en die vanaf het LAN niet, is het ontbrekende stuk de sprong of de route, niet het bindadres. Start OpenVPN binnen de naamruimte in plaats van een levend tun-apparaat erin te schuiven, want het verplaatsen van de interface schakelt die uit en kan routes wissen die je daarna van buitenaf niet meer kunt repareren. Houd de herstelcommando's op de console, niet in de gevangenis.

Gerelateerde artikelen