Hvorfor en Docker-container ikke når verter bak VPN-en
Brocontainere har sitt eget navnerom, så vertens tunnel er usynlig for dem. Sammenlign vertsnettverk, en tun-enhet og macvlan før du redigerer DNS.
En container som ikke når noe bak bedrifts-VPN-en, bor vanligvis i et annet nettverksnavnerom enn tunnelen. Vertsklientens ruter, DNS-servere og brannmurmerker tilhører vertens stabel; en brocontainer har sin egen. Dette ene faktum forklarer de fleste rapportene som når et plattformteam, og det er også grunnen til at «VPN-en er ødelagt» og «Docker omgår VPN-en» kan være feil samtidig. To svært forskjellige oppsett skjuler seg bak ett symptom, så finn ut hvilket du har før du endrer en innstilling.
Finn ut hvis navnerom som eier tunnelen
På Docker Desktop for macOS eller Windows kjører containere inne i en virtuell Linux-maskin. En VPN-klient installert på skrivebordet lager en tunnel i skrivebordets operativsystem, og den virtuelle maskinen ser den aldri. Ingen containerkonfigurasjon retter det, fordi grensesnittet containeren ville trengt ikke finnes i det hele tatt i nettverksnavnerommet dens.
På en Linux-vert bor tunnelen i vertens navnerom, og brocontainere når den vanligvis gjennom vertens rutetabell med kilde-NAT brukt på vei ut. Når den veien svikter, er årsaken vanligvis videresendingspolicy, omvendt sti-filtrering eller et overlappende subnett snarere enn en manglende rute. Bekreft hvilken av de to verdenene du er i før du leser videre:
docker info --format '{{.OperatingSystem}}'
docker run --rm --net=host alpine ip route | head -5
docker run --rm alpine ip route | head -5
Forskjellen mellom de to rutetabellene er hele problemet på én skjerm. Hvis vertens visning inneholder tunngrensesnittet og broens visning ikke gjør det, ser du navneromsisolering, og alt annet er et valg om hvordan man krysser den.
Vertsnettverk er en test, ikke et design
Å kjøre en container med vertsnettverk, som Docker dokumenterer som deling av vertens nettverksnavnerom, får den til å arve tunngrensesnittet og rutene direkte. Hvis den samme forespørselen da lykkes, er ruteteorien bekreftet, og feilen er navneromsisolering fremfor legitimasjon, DNS eller en tilgangsregel.
docker run --rm --net=host curl -sS -o /dev/null -w '%{http_code}\n' https://api.internal/health
Behold det som diagnostikk. Vertsnettverk gir avkall på portpublisering og det meste av isolasjonen du ønsket fra en container, og på Docker Desktop betyr «host» den virtuelle maskinen, ikke skrivebordet, så suksess eller fiasko der kan villede deg hvis du glemmer hvilken vert du henvendte deg til.
En tun-enhet og privilegiene som følger med
En VPN-klient inne i containeren trenger en tunnelenhet og tillatelse til å konfigurere den. Den vanlige snarveien er --privileged, som gir alle enheter og lemper sikkerhetspolicyen i hele containeren. Det er langt mer enn denne oppgaven krever, og det er vanskelig å forsvare i en gjennomgang.
sudo modprobe tun
docker run --rm -it --device /dev/net/tun --cap-add NET_ADMIN myvpn-client
Den smalere formen mapper den enkelte enhetsnoden og legger bare til nettverksadministrasjonskompetansen. Last inn modulen på verten først slik at noden finnes. Hvis containeren starter og klienten rapporterer at den ikke kan åpne tunnelenheten, sjekk mappingen før du mistenker profilen, fordi den feilen vanligvis er bokstavelig.
Dette designet betyr også at klienten kjører per container. Det er det riktige svaret når hver arbeidsbelastning trenger sin egen tunnel, og det gale når du bare ville at vertens tunnel skulle være synlig, noe plattformteamet sannsynligvis antok at du gjorde.
Bro-NAT endrer kilden VPN-en ser
Med standardbroen oversettes containernes utgående trafikk til vertens adresse. Bak en VPN ser bedriftssiden derfor vertens tunneladresse i stedet for containerens, tilgangsregler per kilde oppfører seg som om verten sendte forespørselen, og to containere blir uskillbare for VPN-serveren.
macvlan eller ipvlan gir i stedet containeren en LAN-adresse, noe som hjelper LAN-oppdagelse og får containeren til å se ut som en jevnbyrdig på segmentet. Det omgår også vertens tunnel fullstendig, så en slik container når ikke kun-VPN-prefikser med mindre VPN-en også er tilgjengelig fra det LAN-et.
Begge formene er legitime; de svarer på ulike krav. Hvis kravet er «denne containeren må nå en kun-VPN-tjeneste», velger du mellom ruting gjennom verten og å avslutte tunnelen inne i containeren. Skriv ned det valget før utrullingen, ikke etter den første mislykkede forespørselen. Uansett hva du velger, registrer kildeadressen den fjerne enden vil se, for det er den tilgangsreglene og loggene dens vil vise. Et design som ikke kan oppgi den adressen, er ikke ferdig.
DNS følger daemonen, ikke tunnelen
En container får resolver-konfigurasjonen sin ved oppstart, kopiert fra daemonen eller fra imaget. Adresser som VPN-en dytter etter tilkobling, kommer for sent for den kopien, og de dyttes til vertens resolver i stedet for inn i containeren.
Angi resolveren eksplisitt for tjenesten, eller pek den mot en intern resolver som er tilgjengelig gjennom tunnelen. En container som løser et privat navn til en offentlig adresse, bruker vanligvis en offentlig resolver, ikke en brutt rute, og rettelsen hører hjemme i compose-filen eller daemonkonfigurasjonen.
Samme resonnement gjelder spørsmålet om utgangsadressen. Hvis hver container må fremstå fra en annen VPN-adresse, kan én vertstunnel ikke levere det fordi NAT slår dem sammen til én kilde. De gangbare formene er en klient i hver containers navnerom eller en sidecar som eier tunnelen og deler stabelen sin, og begge endrer hvordan applikasjonen adresseres.
Sjekkliste før du lukker saken: identifiser navnerommet som eier tunnelen, bevis veien med vertsnettverk, kartlegg bare den nødvendige tun-enheten, husk kildeadressen etter NAT, angi resolveren eksplisitt og behandle utgangsadresser per container som en arkitekturbeslutning fremfor et flagg.