Opravte prevádzku Dockeru a WSL, ktorá ignoruje VPN hostiteľa
Kontajnery a WSL si držia vlastné trasy, resolver a cestu preposielania, takže fungujúci tunel hostiteľa ich necháva so zastaraným DNS alebo bez východu. Opravte každú vrstvu.
Túto jar som strávil väčšinu jedného rána naháňaním kontajnera, ktorý nedokázal vyriešiť ani jedno interné meno, kým prehliadač vedľa neho otváral wiki bez sťažnosti. Tunel bol hore, prehliadač to dokazoval a kontajner zostával v inom sieťovom mennom priestore s inou smerovacou tabuľkou a iným resolverom. Nasleduje poradie, ktoré teraz kontrolujem: najprv smerovacie tabuľky, potom preklad mien, potom preposielanie a nakoniec platforma hostiteľa. Zastavte sa pri prvom kroku, ktorý už zlyháva, pretože pridávanie pravidiel nižšie v zásobníku hranicu skrýva, namiesto toho, aby ju posunulo.
Porovnajte tri smerovacie tabuľky, skôr než zmeníte pravidlo
Kontajner na predvolenom moste Dockeru má jednu predvolenú trasu smerujúcu na bránu docker0 a netuší, že tun0 existuje. Hostiteľ má tun0, trasy, ktoré VPN pretlačila, a možno pravidlo politiky, ktoré posiela testovaciu prevádzku cez iné rozhranie, než očakávate. WSL pridáva tretiu tabuľku za vlastným virtuálnym adaptérom. Vypíšte všetky tri, skôr než ktorúkoľvek upravíte.
| Context | Command | What a wrong answer looks like |
|---|---|---|
| Host | ip route get 10.8.0.20 | Leaves a physical interface instead of tun0 |
| Container | ip route | Only 172.17.0.0/16 via 172.17.0.1 |
| Container DNS | cat /etc/resolv.conf | A public resolver, or an upstream the tunnel never pushed |
| WSL | ip addr; ip route | Only the WSL subnet, no Windows VPN adapter |
Ak je jedinou trasou kontajnera most a tun0 sa v jeho mennom priestore nikdy neobjaví, nič nižšie nepomôže: žiadna zmena menného servera nevytvorí trasu a žiadna trasa nevytvorí identitu tunela, ktorú partner prijme. Poradie je dôležité, pretože zlyhanie DNS a zlyhanie trasy vyzerajú zvnútra shellu rovnako.
Nasmerujte resolver na tunel namiesto verejného
Na hostiteľovi, resolvectl status vypisuje servery DNS pre každé spojenie, a readlink -f /etc/resolv.conf vám povie, či je súbor stub systemd, súbor NetworkManager alebo niečo, čo prepísal klient dodávateľa. Vnútri kontajnera v používateľom definovanej sieti, /etc/resolv.conf pomenúva 127.0.0.11, vstavaný resolver Dockeru, ktorý preposiela na ten upstream, s ktorým bol démon nakonfigurovaný. Kontajner na predvolenom moste však pri vytvorení dostal kópiu súboru hostiteľa a drží si ju.
Tá kópia je dôvod, prečo tunel, ktorý sa zdvihne po štarte kontajnera, necháva kontajner pýtať sa starého upstreamu. Buď odovzdajte resolver VPN výslovne pomocou docker run --dns 10.8.0.53, alebo nastavte "dns": ["10.8.0.53"] v /etc/docker/daemon.json a reštartujte démona, alebo kontajner znovu vytvorte, keď je tunel hore. Znovuvytvorenie je zvyčajne lacnejšie než ladenie resolvera, ktorý bol pred hodinou správny.
Nahradenie verejným resolverom je oprava, ktorá zachováva príznak. Preloží internet a zlyhá v každej súkromnej zóne a môže potichu obísť filtrovanie, pre ktoré tunel existuje. Ak sa pokúsite zapisovať do /etc/resolv.conf bežiaceho kontajnera, očakávajte Device or resource busy: Docker ten súbor bind-mountuje, takže úprava najprv potrebuje odpojenie. Nastavenie --dns pri vytvorení je postupnosť, ktorá prežije reštart.
Preposielajte a prekladajte, keď si kontajnery požičiavajú tunel
S predvoleným mostom je hostiteľ smerovačom medzi docker0 a tun0 a predvolene nevykonáva ani jednu z týchto úloh. Zapnite preposielanie a preložte zdrojovú adresu, aby partner videl adresu tunela hostiteľa namiesto adresy, ku ktorej nemá spätnú trasu (nahraďte tun0 tým, ako váš klient nazýva rozhranie):
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 ACCEPTPravidlá FORWARD sú dôležité na hostiteľoch, ktorých politika preposielania je DROP. Docker vkladá svoje vlastné reťaze, preto testujte paketom, nie čítaním iptables -S: z kontajnera, ip route get 10.8.0.20 by malo pomenovať bránu mosta, a nc -vz 10.8.0.20 443 by sa malo pripojiť alebo vypršať na tuneli, nie na resolvery.
Bez MASQUERADE partner potrebuje spätnú trasu do 172.17.0.0/16, ktorú väčšina VPN so vzdialeným prístupom nepretlačí. Tu sa tiež láme plán u klienta založeného na politikách: ak zachytáva len prevádzku konkrétnych UID alebo cgroups, vaše pravidlá preposielania paket vnútri tunela nikdy nevidia, a oprava patrí do smerovacej politiky klienta, nie do iptables. Pravidlá pridané ručne zmiznú pri reštarte, preto ich dajte do systemd jednotky alebo tabuľky netfilter-persistent a po reštarte znova otestujte, keďže tunel, ktorý sa zdvihne neskoro, ich môže zmyť.
Umiestnite tunel dovnútra kontajnera, keď je cieľom izolácia
Ak musí jeden kontajner vychádzať cez konkrétny uzol, spustite klienta v tomto kontajneri. Potrebuje --cap-add NET_ADMIN a --device /dev/net/tun, a potom vlastní svoj tun0, trasy a firewall. Ak cez neho prechádzajú iné kontajnery, potrebuje aj preposielanie a pravidlo MASQUERADE vnútri kontajnera, a tí partneri potrebujú výslovnú trasu alebo proxy, ktorá naň ukazuje; predvolený most Dockeru tú trasu za vás nepridá.
Sieť hostiteľa, docker run --network host, je lacná verzia: kontajner sa pripojí k mennému priestoru hostiteľa a vidí trasy tunela priamo. Zanecháva však izoláciu siete, pozýva kolízie portov a v praxi je to možnosť Linuxu. Publikovaný port nie je náhrada. -p 8080:80 sprístupní službu z hostiteľa; nesprístupní interné adresy 10.x zvnútra kontajnera, a miešanie týchto dvoch vecí je spôsob, akým sa problém smerovania zmení na otvorený port databázy.
Odlište zlyhanie mena od prekrývajúcej sa podsiete
Predvolený most Dockeru je 172.17.0.0/16 a mnohé firemné fondy VPN ležia vnútri 172.16.0.0/12. Keď tunel vlastní ten rozsah, prevádzka určená kontajneru sa môže namiesto toho smerovať do tunela. Mená zlyhávajú, chyba vyzerá ako DNS a problém je v adresách. Kontrolujte cieľ, nie resolver: ip route get 172.17.0.5 na hostiteľovi, potom porovnajte prefix mosta s fondom VPN a s docker network inspect bridge --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'.
Oprava spočíva v posunutí jedného z rozsahov: buď iný predvolený fond adries pre Docker v daemon.json alebo iný fond na koncentrátore. Pridanie ďalšieho menného servera tu nič neurobí, a rovnako ssh -b: pripútanie klienta k rozhraniu mení zdrojovú adresu, nie cieľovú trasu, ktorá vedie do tunela. Rýchla deľba práce: meno, ktoré sa preloží na hostiteľovi, ale nie v kontajneri, je problém resolvera, kým priame IP spojenie, ktoré v kontajneri visí, ale na hostiteľovi funguje, je problém trasy alebo preposielacieho reťazca.
WSL a Docker Desktop nerešpektujú pravidlá Linuxu
V predvolenom režime NAT sedí WSL za vlastným virtuálnym adaptérom a nedostáva interné trasy ani DNS prípony VPN Windows, a preto prehliadač funguje a ping vnútri distribúcie nie. Zrkadlová sieť, dostupná v nedávnych zostaveniach Windows 11, namiesto toho zdieľa rozhrania hostiteľa, ale musí sa zapnúť v .wslconfig a distribúcia reštartovať pomocou wsl --shutdown. Overte aktívny režim pomocou wslinfo --networking-mode pred aplikovaním opravy, pretože odpoveď NAT je nesprávna pre zrkadlový režim a naopak.
Docker Desktop pridáva ďalšiu vrstvu. Kontajnery Linuxu na Windows sedia za implementáciou NAT historicky nazývanou vpnkit a ich cesta sa líši od natívneho hostiteľa Linuxu. Kontajnery Windows sa pripájajú cez virtuálny prepínač Hyper-V a firemný klient môže blokovať prevádzku z tohto prepínača, takže kontajnery Linuxu na tom istom stroji sa môžu dostať do siete, kým kontajnery Windows nemajú nič. Externý prepínač pripútaný k fyzickému adaptéru je bežné riešenie a mení sieťovú identitu kontajnera spôsobmi, ktoré politika nemusí dovoliť.
Skôr než napíšete ďalšie pravidlo, prejdite štyri vrstvy v poradí a zastavte sa tam, kde je jedna z nich nesprávna:
- Vnútri kontajnera: dosiahne
ip routesúkromný prefix a pomenúva/etc/resolv.confupstream, ktorý ho preloží? - Na hostiteľovi: je zapnuté preposielanie, je NAT pripútaný k rozhraniu tunela a prijíma preposielací reťazec most k tunelu?
- Na partnerovi: pozná spätnú cestu, alebo sa spoliehate na NAT, aby skryl podsieť kontajnera?
- Na platforme: je WSL v režime NAT alebo zrkadlovom a je kontajner Linux alebo Windows?
Spustite každý test znova v novom kontajneri alebo shelli. Dlho bežiaci proces s uloženou odpoveďou alebo nadviazaným spojením bude zlyhávať aj po tom, čo je konfigurácia správna, a toto zlyhanie vyzerá presne ako oprava, ktorá nefungovala.