Een container die niets achter de bedrijfs-VPN bereikt, leeft meestal in een andere netwerknaamruimte dan de tunnel. De routes, DNS-servers en firewallmarkeringen van de hostclient horen bij de stack van de host; een bridge-container heeft de zijne. Dat ene feit verklaart de meeste meldingen die een platformteam bereiken, en het is ook de reden waarom «de VPN is kapot» en «Docker omzeilt de VPN» allebei tegelijk onjuist kunnen zijn. Achter één symptoom schuilen twee heel verschillende opstellingen, dus stel vast welke u hebt voordat u een instelling wijzigt.

Zoek uit wiens naamruimte de tunnel bezit

Op Docker Desktop voor macOS of Windows draaien containers in een virtuele Linux-machine. Een VPN-client die op de desktop is geïnstalleerd, maakt een tunnel in het besturingssysteem van de desktop, en de virtuele machine ziet die nooit. Geen enkele containerconfiguratie lost dat op, omdat de interface die de container nodig zou hebben helemaal niet bestaat in zijn netwerknaamruimte.

Op een Linux-host leeft de tunnel in de naamruimte van de host, en bridge-containers bereiken hem meestal via de routingtabel van de host, met source-NAT toegepast op de uitgaande weg. Als dat pad faalt, is de oorzaak meestal doorstuurbeleid, reverse-path-filtering of een overlappend subnet in plaats van een ontbrekende route. Bevestig in welke van de twee werelden u zit voordat u verder leest:

docker info --format '{{.OperatingSystem}}'
docker run --rm --net=host alpine ip route | head -5
docker run --rm alpine ip route | head -5

Het verschil tussen die twee routingtabellen is het hele probleem op één scherm. Als de weergave van de host de tunnelinterface bevat en die van de bridge niet, kijkt u naar naamruimte-isolatie, en al het andere is een keuze over hoe u die oversteekt.

Hostnetwerken is een test, geen ontwerp

Een container met hostnetwerken laten draaien, wat Docker documenteert als het delen van de netwerknaamruimte van de host, laat hem de tunnelinterface en zijn routes rechtstreeks erven. Als hetzelfde verzoek dan slaagt, is de routetheorie bevestigd en is de storing naamruimte-isolatie, niet referenties, DNS of een toegangsregel.

docker run --rm --net=host curl -sS -o /dev/null -w '%{http_code}\n' https://api.internal/health

Houd het als diagnostiek. Hostnetwerken geeft poortpublicatie en het grootste deel van de isolatie die u van een container wilde op, en op Docker Desktop betekent «host» de virtuele machine, niet de desktop, dus een succes of mislukking daar kan u misleiden als u vergeet welke host u aansprak.

Een tun-apparaat en de privileges die erbij horen

Een VPN-client in de container heeft een tunnelapparaat en toestemming nodig om het te configureren. De gebruikelijke snelkoppeling is --privileged, dat elk apparaat toekent en het beveiligingsbeleid in de hele container versoepelt. Dat is veel meer dan deze taak vereist, en het is moeilijk te verantwoorden in een review.

sudo modprobe tun
docker run --rm -it --device /dev/net/tun --cap-add NET_ADMIN myvpn-client

De smallere vorm koppelt het enkele apparaatknooppunt en voegt alleen de netwerkbeheercapaciteit toe. Laad eerst de module op de host zodat het knooppunt bestaat. Als de container start en de client meldt dat hij het tunnelapparaat niet kan openen, controleer dan de koppeling voordat u het profiel verdenkt, want die fout is meestal letterlijk.

Dit ontwerp betekent ook dat de client per container draait. Dat is het juiste antwoord wanneer elke werklast zijn eigen tunnel nodig heeft, en het verkeerde wanneer u alleen de tunnel van de host zichtbaar wilde hebben, wat het platformteam waarschijnlijk aannam dat u deed.

Bridge-NAT verandert de bron die de VPN ziet

Met de standaardbridge wordt uitgaand containerverkeer vertaald naar het adres van de host. Achter een VPN ziet de bedrijfskant daarom het tunneladres van de host en niet dat van de container, toegangsregels per bron gedragen zich alsof de host het verzoek deed, en twee containers worden voor de VPN-server niet te onderscheiden.

macvlan of ipvlan geeft de container in plaats daarvan een LAN-adres, wat helpt bij LAN-detectie en de container als een gelijke op het segment laat lijken. Het omzeilt ook de tunnel van de host volledig, dus zo'n container bereikt geen alleen-VPN-prefixen tenzij de VPN ook vanaf dat LAN bereikbaar is.

Beide vormen zijn legitiem; ze beantwoorden verschillende eisen. Als de eis is «deze container moet een alleen-VPN-dienst bereiken», kiest u tussen routeren via de host en de tunnel binnen de container beëindigen. Schrijf die keuze op vóór de uitrol, niet na het eerste mislukte verzoek. Wat u ook kiest, noteer het bronadres dat de verre kant zal zien, want dat is wat zijn toegangsregels en zijn logboeken tonen. Een ontwerp dat dat adres niet kan noemen, is niet af.

DNS volgt de daemon, niet de tunnel

Een container krijgt zijn resolverconfiguratie bij het starten, gekopieerd van de daemon of van de image. Adressen die de VPN na het verbinden pusht, komen te laat voor die kopie, en ze worden naar de resolver van de host gepusht in plaats van in de container.

Stel de resolver expliciet in voor de dienst, of wijs hem naar een interne resolver die via de tunnel bereikbaar is. Een container die een privénaam naar een openbaar adres omzet, gebruikt meestal een openbare resolver, lijdt niet onder een kapotte route, en de correctie hoort in het compose-bestand of de daemonconfiguratie.

Dezelfde redenering geldt voor de vraag naar het uitgangsadres. Als elke container vanaf een ander VPN-adres moet verschijnen, kan één tunnel van de host dat niet leveren omdat NAT ze tot één bron samenvat. De werkbare vormen zijn een client in de naamruimte van elke container of een sidecar die de tunnel bezit en zijn stack deelt, en beide veranderen hoe de applicatie geadresseerd wordt.

Checklist voordat u het ticket sluit: identificeer de naamruimte die de tunnel bezit, bewijs het pad met hostnetwerken, koppel alleen het benodigde tun-apparaat, onthoud het bronadres na NAT, stel de resolver expliciet in en behandel uitgangsadressen per container als een architectuurbeslissing en niet als een vlag.

Gerelateerde artikelen