Eg brukte det meste av ein formiddag denne våren på å jage ein containar som ikkje klarte å slå opp eit einaste internt namn, medan nettlesaren ved sida av opna wikien utan klager. Tunnelen var oppe, nettlesaren prova det, og containaren låg i eit anna nettverksnamnerom med ein annan rutetabell og ein annan resolver. Det som følgjer, er rekkjefølgja eg sjekkar no: rutetabellar først, oppslag neste, vidaresending tredje og vertsplattforma til slutt. Stopp ved det første trinnet som alt feilar, fordi reglar lenger nede i stakken gøymer grensa i staden for å flytte ho.

Samanlikn dei tre rutetabellane før du endrar ein regel

Ein containar på standardbrua til Docker har éi standardrute mot docker0-gatewayen og veit ikkje at tun0 finst. Verten har tun0, rutene VPN-en dytta, og kanskje ein policynorm som sender prøvetrafikk ut gjennom eit anna grensesnitt enn du ventar. WSL legg til ein tredje tabell bak sin eigen virtuelle adapter. Skriv ut alle tre før du redigerer nokon av dei.

ContextCommandWhat a wrong answer looks like
Hostip route get 10.8.0.20Leaves a physical interface instead of tun0
Containerip routeOnly 172.17.0.0/16 via 172.17.0.1
Container DNScat /etc/resolv.confA public resolver, or an upstream the tunnel never pushed
WSLip addr; ip routeOnly the WSL subnet, no Windows VPN adapter

Viss den einaste ruta til containaren er brua og tun0 aldri dukkar opp i namneromet hans, hjelper ingenting nedanfor: inga namneserverendring lagar ei rute, og inga rute lagar ein tunnelidentitet peer-en vil godta. Rekkjefølgja er viktig fordi ein DNS-feil og ein rutefeil ser like ut innanfrå eit skal.

Pek resolveren mot tunnelen i staden for mot ein offentleg

På verten, resolvectl status listar DNS-tenarar per lenkje, og readlink -f /etc/resolv.conf fortel deg om fila er systemd-stubben, ei NetworkManager-fil eller noko ein leverandørklient har skrive om. Inne i ein containar på eit brukardefinert nettverk, /etc/resolv.conf namngir 127.0.0.11, den innebygde resolveren til Docker, som vidaresender til den upstreamen daemonen vart konfigurert med. Ein containar på standardbrua fekk derimot ein kopi av vertsfila då han vart oppretta, og held på ho.

Den kopien er grunnen til at ein tunnel som kjem opp etter at containaren startar, lèt containaren spørje den gamle upstreamen. Anten sender du VPN-resolveren eksplisitt med docker run --dns 10.8.0.53, eller set "dns": ["10.8.0.53"] i /etc/docker/daemon.json og startar daemonen på nytt, eller opprettar containaren på nytt når tunnelen er oppe. Oppretting på nytt er vanlegvis billegare enn å feilsøkje ein resolver som var rett for ein time sidan.

Å bytte til ein offentleg resolver er reparasjonen som bevarar symptomet. Han løyser internett og feilar i kvar privat sone, og han kan stille omgå filtreringa som tunnelen finst for å handheve. Viss du prøver å skrive inne i /etc/resolv.conf på ein køyrande containar, vent Device or resource busy: Docker bind-mountar den fila, så endringa krev først ei avmontering. Å setje --dns ved oppretting er sekvensen som overlever ein omstart.

Vidaresend og omset når containarar låner tunnelen

Med standardbrua er verten ein ruter mellom docker0 og tun0, og som standard gjer han ingen av delane. Slå på vidaresending og omset kjeldeadressa slik at peer-en ser ei tunneladresse på verten i staden for ei han ikkje har returrute til (byt ut tun0 med det klienten din kallar grensesnittet):

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
iptables -A FORWARD -i docker0 -o tun0 -j ACCEPT
iptables -A FORWARD -i tun0 -o docker0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

FORWARD-reglane er viktige på vertar der vidaresendingspolitikken er DROP. Docker set inn eigne kjeder, så test med ein pakke i staden for å lese iptables -S: frå containaren, ip route get 10.8.0.20 skal namngi brua sin gateway, og nc -vz 10.8.0.20 443 skal kople til eller få tidsavbrot ved tunnelen i staden for ved resolveren.

Utan MASQUERADE treng peer-en ei returrute til 172.17.0.0/16, som dei fleste fjernåtkomst-VPN ikkje dyttar. Det er òg her ein policybasert klient øydelegg planen: viss han berre fangar trafikk frå visse UID-ar eller cgroups, ser vidaresendingsreglane dine aldri pakken inne i tunnelen, og rettinga høyrer heime i ruteringspolitikken til klienten og ikkje i iptables. Reglar som vert lagde til manuelt, forsvinn ved omstart, så legg dei i ei systemd-eining eller ein netfilter-persistent-tabell og test på nytt etter ein omstart, sidan ein tunnel som kjem seint opp kan skylje dei bort.

Legg tunnelen inne i containaren når isolasjon er målet

Viss éin containar må gå ut gjennom ein bestemd node, køyr klienten i den containaren. Han treng --cap-add NET_ADMIN og --device /dev/net/tun, og då eig han sin eigen tun0, ruter og brannmur. Viss andre containarar passerer gjennom han, treng han òg vidaresending og ein MASQUERADE-regel inne i containaren, og dei peer-ane treng ei eksplisitt rute eller proxy som peikar på han; standardbrua til Docker legg ikkje til den ruta for deg.

Vertsnettverk, docker run --network host, er den billege versjonen: containaren blir med i namneromet til verten og ser tunnelrutene direkte. Det droppar òg nettverksisolering, inviterer portkollisjonar og er i praksis eit Linux-alternativ. Ein publisert port er ikkje ei erstatning. -p 8080:80 gjer ein teneste tilgjengeleg frå verten; det gjer ikkje interne 10.x-adresser tilgjengelege frå innsida av containaren, og å blande dei to er måten eit ruteringsproblem blir ein eksponert databaseport.

Skil ein namnefeil frå eit overlappande subnett

Standardbrua til Docker er 172.17.0.0/16, og mange bedrifts-VPN-puljer ligg innanfor 172.16.0.0/12. Når tunnelen eig det området, kan trafikk meint for ein containar bli ruta inn i tunnelen i staden. Namn feilar, feilen ser ut som DNS, og problemet er adressene. Sjekk destinasjonen, ikkje resolveren: ip route get 172.17.0.5 på verten, samanlikn så bruoprefikset med VPN-pulja og med docker network inspect bridge --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'.

Reparasjonen er å flytte eitt av områda: anten ein annan standardadressepulje for Docker i daemon.json eller ein annan pulje på konsentratoren. Å leggje til ein namneserver til gjer ingenting her, og det gjer ssh -b heller ikkje: å binde klienten til eit grensesnitt endrar kjeldeadressa, ikkje ei destinasjonsrute som peikar inn i tunnelen. Rask arbeidsdeling: eit namn som blir løyst på verten men ikkje i containaren, er eit resolverproblem, medan ei direkte IP-tilkopling som heng i containaren men verkar på verten, er eit rute- eller vidaresendingskjeproblem.

WSL og Docker Desktop følgjer ikkje Linux-reglane

I sin standard NAT-modus sit WSL bak sin eigen virtuelle adapter og får ikkje dei interne rutene eller DNS-suffiksa til Windows-VPN-en, og difor verkar nettlesaren og ping inne i distribusjonen ikkje. Spegla nettverk, som er tilgjengeleg i nyare Windows 11-bygg, deler i staden grensesnitta til verten, men det må slåast på i .wslconfig og distribusjonen må startast på nytt med wsl --shutdown. Stadfest den aktive modusen med wslinfo --networking-mode før du brukar ei retting, fordi NAT-svaret er feil for speglamodus og omvendt.

Docker Desktop legg til endå eit lag. Linux-containarar på Windows sit bak ein NAT-implementasjon som historisk heiter vpnkit, og vegen deira skil seg frå ein innfødd Linux-vert. Windows-containarar koplar til via ein virtuell Hyper-V-brytar, og ein bedriftsklient kan blokkere trafikk frå den brytaren, så Linux-containarar på same maskin kan nå nettverket medan Windows-containarar ikkje har noko. Ein ekstern brytar bunden til den fysiske adapteren er den vanlege løysinga, og han endrar nettverksidentiteten til containaren på måtar politikken kanskje ikkje tillèt.

Før du skriv endå ein regel, gå gjennom dei fire laga i rekkjefølgje og stopp der eitt av dei er feil:

  • Inne i containaren: når ip route det private prefikset, og namngir /etc/resolv.conf ein upstream som løyser det?
  • På verten: er vidaresending på, er NAT bunden til tunnelgrensesnittet, og godtek vidaresendingskjeda bru til tunnel?
  • På peer-en: kjenner han ein returveg, eller reknar du med at NAT gøymer subnettet til containaren?
  • På plattforma: er WSL i NAT- eller speglamodus, og er containaren Linux eller Windows?

Køyr kvar test på nytt i ein fersk containar eller eit ferskt skal. Ein langvarig prosess med bufra svar eller ei etablert tilkopling vil halde fram med å feile etter at konfigurasjonen er rett, og den feilen ser nøyaktig ut som ei retting som ikkje verka.

Relaterte artiklar