Stel je een Linux-host voor die een VPN beëindigt en tegelijk een container op een macvlan-netwerk draait. Het LAN is 192.168.60.0/24, de container heeft 192.168.60.210, en VPN-clients komen van 10.95.0.0/24. De client bereikt de dienst, het antwoord komt nooit terug, en elke firewallregel op de host lijkt correct. Twee afzonderlijke beperkingen veroorzaken dat symptoom, en het oplossen van de ene laat de andere staan.

Twee beperkingen, één symptoom

De eerste beperking is isolatie: de macvlan-stuurprogramma van Docker staat een container niet toe om via de bovenliggende interface met zijn eigen host te praten. Verkeer tussen de host-stack en de container heeft geen pad, hoe de routes op de host ook zijn geschreven.

De tweede beperking is de terugweg. De standaardgateway van de container is meestal de LAN-router, dus een antwoord aan een VPN-client gaat via die router naar buiten. Als de router geen route terug naar de VPN-pool heeft, wordt het antwoord ergens in het midden weggegooid.

De twee storingen zien er vanaf de client identiek uit: een verzoek dat aankomt en een antwoord dat nooit komt. Ze vragen om verschillende reparaties, en een brede masquerade-regel kan verbergen welke van de twee nog stuk is. Daarom is de eerste test een opname aan de containerkant en niet nog een firewallwijziging. Als het verzoek daar nooit verschijnt, is de isolatiebeperking aan de orde.

Bouw de shim aan de hostkant, smal

Een tweede macvlan-interface op de host, in bridgemodus gekoppeld aan dezelfde bovenliggende interface, geeft de host-stack een eigen identiteit op dat LAN-segment. Reserveer ervoor een adres buiten de DHCP-pool en buiten het containerbereik, en routeer alleen de container erdoor.

ip link add macvlan-vpn link eth0 type macvlan mode bridge
ip address add 192.168.60.250/32 dev macvlan-vpn
ip link set macvlan-vpn up
ip route add 192.168.60.210/32 dev macvlan-vpn src 192.168.60.250

De eerste opdracht maakt de interface in bridgemodus aan, wat de gedocumenteerde standaard voor dit stuurprogramma is en de modus die je wilt voor verkeer tussen host en container. De tweede kent een /32 toe zodat het adres niet botst met het LAN-prefix, en de vierde stuurt alleen het adres van de container via de shim.

Leid niet het hele LAN via de nieuwe interface om. De gewone verbonden route blijft zoals hij is, en de hostroute is bewust smal zodat één container een pad krijgt zonder dat de rest van het segment zijn gedrag verandert. Een standaardroute naar de shim zou een ander ontwerp met andere gevolgen zijn. Houd hem specifiek en de schade blijft klein.

Deze opdrachten wijzigen de netwerkconfiguratie op een draaiende host. Op een apparaat of een beheerd platform gebruik je het ondersteunde configuratiemechanisme van dat platform, want een interactieve wijziging in een root-shell overleeft een upgrade misschien niet.

Bepaal hoe de bron behouden blijft

Met de shim op zijn plaats kan de container de host bereiken, en de vraag wordt welk bronadres het antwoord draagt. De oorspronkelijke VPN-bron behouden is het schonere model: de container ziet het echte clientadres, en de logs en toegangsregels van de dienst kunnen het gebruiken.

Om dat te laten werken moet de netwerkconfiguratie van de container voor dit pad verkeer voor 10.95.0.0/24 naar 192.168.60.250 sturen als zijn gateway. Dat is een ondersteunde route- of gatewayinstelling binnen de configuratie van de container zelf, geen truc aan de hostkant. Bevestig het van binnenuit de container in plaats van aan te nemen dat de instelling is ingegaan. Een standaardgateway die nog naar de LAN-router wijst, blijft antwoorden in hetzelfde gat sturen.

Als het goedgekeurde ontwerp in plaats daarvan de VPN-bronnen verbergt, beperk de vertaling dan smal: de echte VPN-pool, de shim als uitgaande interface, en de specifieke container en dienst.

iptables -t nat -A POSTROUTING -s 10.95.0.0/24 -o macvlan-vpn -j SNAT --to-source 192.168.60.250

Laat de shim overeenkomen als uitgaande interface, niet de tunnel. Een regel die de tunnel als uitgaande interface noemt, komt niet overeen met een pakket op weg naar de container, en dat is precies de fout die zo'n opstelling meestal bevat. Houd de regel zo smal als de zin hierboven en herzie hem wanneer de pool verandert.

Controleer vanaf de client, niet vanaf de host

Een verzoek van de host zelf, gebonden aan het adres van de shim, bewijst dat de shim de container kan bereiken. Het bewijst niet dat de container verkeer kan terugsturen naar een bewaarde bron 10.95.0.x, want het bronadres in die test is dat van de shim zelf.

curl -sS --interface 192.168.60.250 -o /dev/null -w '%{http_code}\n' http://192.168.60.210:8080/health
sudo tcpdump -ni macvlan-vpn host 192.168.60.210

De eerste opdracht test het stuk van host naar container, en de tweede laat zien wat er werkelijk door de shim gaat terwijl een echte VPN-client het verzoek doet. Kijk naar het bronadres op de weg naar binnen en of er een antwoord met dezelfde flow verschijnt.

Doorsturen moet op de host zijn ingeschakeld, en het doorstuurpad heeft een toestemming nodig voor de VPN-pool naar de shim op de dienstpoort plus bestaande antwoorden. Een INPUT-regel op de host machtigt doorgestuurd verkeer niet, en dat is een veelvoorkomende reden dat het pakket wordt weggegooid nadat de routering correct lijkt.

Draai de echte toepassing met echte inloggegevens en controleer dan of een tweede, ongerelateerde dienst op dezelfde container je nog steeds weigert. Als de enige manier om het werkend te krijgen was om elke doorstuurregel te openen, is het ontwerp niet af. Noteer ook welk bronadres de dienst heeft vastgelegd, want dat zullen zijn eigen toegangsregels vanaf nu gebruiken.

Gerelateerde artikelen