Parandage Dockeri ja WSL-i liiklus, mis eirab hosti VPN-i
Konteinerid ja WSL hoiavad oma marsruute, resolverit ja edastusteed, seega töötav hosti tunnel jätab nad vananenud DNS-i või väljapääsuta. Parandage iga kiht.
Veetsin selle kevade ühe hommiku suurema osa ühte konteinerit taga ajades, mis ei suutnud lahendada ühtegi sisemist nime, samal ajal kui kõrval olev brauser avas wiki ilma kurtmata. Tunnel oli üleval, brauser tõestas seda, ja konteiner seisis teises võrgu nimeruumis, millel oli teine marsruutide tabel ja teine resolver. Järgnev on järjekord, mida ma nüüd kontrollin: kõigepealt marsruutide tabelid, teiseks nime lahendamine, kolmandaks edastamine ja lõpuks hosti platvorm. Peatuge esimesel sammul, mis juba nurjub, sest reeglite lisamine virna allosas peidab piiri, selle asemel et seda liigutada.
Võrrelge kolme marsruutide tabelit enne reegli muutmist
Dockeri vaikimisi sillal oleval konteineril on üks vaikimisi marsruut, mis osutab docker0 lüüsile, ja tal pole aimugi, et tun0 olemas on. Hostil on tun0, VPN-i lükatud marsruudid ja võib-olla poliitikareegel, mis saadab sondiliikluse läbi teise liidese, kui ootate. WSL lisab oma virtuaalse adapteri taha kolmanda tabeli. Printige kõik kolm enne, kui ühtegi neist muudate.
| 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 |
Kui konteineri ainus marsruut on sild ja tun0 ei ilmu kunagi selle nimeruumi, ei aita miski allpool: ükski nimeserveri muudatus ei loo marsruuti ja ükski marsruut ei loo tunneli identiteeti, mille partner vastu võtab. Järjekord on oluline, sest DNS-i tõrge ja marsruudi tõrge näevad kestast seest identsed välja.
Suunake resolver tunnelile, mitte avalikule
Hostil, resolvectl status loetleb DNS-serverid lingi kohta ja readlink -f /etc/resolv.conf ütleb teile, kas fail on systemd stub, NetworkManageri fail või midagi, mille tarnija klient ümber kirjutas. Kasutaja määratud võrgus oleva konteineri sees, /etc/resolv.conf nimetab 127.0.0.11, Dockeri sisseehitatud resolveri, mis edastab sellele upstreamile, millega deemon konfigureeriti. Vaikimisi silla konteiner sai seevastu loomisel hosti faili koopia ja hoiab seda.
See koopia on põhjus, miks tunnel, mis tõuseb pärast konteineri käivitumist, jätab konteineri vana upstreami pärima. Kas edastage VPN-i resolver selgesõnaliselt käsuga docker run --dns 10.8.0.53, või seadke "dns": ["10.8.0.53"] failis /etc/docker/daemon.json ja taaskäivitage deemon, või looge konteiner uuesti, kui tunnel on üleval. Uuesti loomine on tavaliselt odavam kui resolveri silumine, mis oli tund aega tagasi õige.
Avaliku resolveri vastu vahetamine on parandus, mis säilitab sümptomi. See lahendab interneti ja nurjub igas privaatses tsoonis ning võib vaikselt mööda minna filtreerimisest, mille jaoks tunnel eksisteerib. Kui proovite kirjutada /etc/resolv.conf töötava konteineri sees, oodake Device or resource busy: Docker bind-mountib selle faili, seega vajab muudatus kõigepealt lahtimonteerimist. --dns loomisel seadmine on järjestus, mis elab üle taaskäivituse.
Edastage ja tõlkige, kui konteinerid tunneli laenavad
Vaikimisi sillaga on host marsruuter docker0 ja tun0 vahel ning vaikimisi ei tee ta kumbagi tööd. Lülitage edastamine sisse ja tõlkige lähteaadress, et partner näeks hosti tunneli aadressi, mitte aadressi, kuhu tal pole tagasimarsruuti (asendage tun0 sellega, kuidas teie klient liidest nimetab):
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 ACCEPTFORWARD-reeglid on olulised hostidel, mille edastamispoliitika on DROP. Docker lisab oma ahelad, seega testige paketiga, mitte lugedes iptables -S: konteinerist peaks ip route get 10.8.0.20 nimetama silla lüüsi ja nc -vz 10.8.0.20 443 ühenduma või aeguma tunnelil, mitte resolveril.
Ilma MASQUERADE-ta vajab partner tagasimarsruuti 172.17.0.0/16-le, mida enamik kaugjuurdepääsu VPN-e ei lükka. Siin läheb plaan katki ka poliitikal põhineva kliendi puhul: kui see püüab ainult kindlate UID-de või cgroups-ide liiklust, ei näe teie edastusreeglid kunagi paketti tunneli sees ja parandus kuulub kliendi marsruutimispoliitikasse, mitte iptablesisse. Käsitsi lisatud reeglid kaovad taaskäivitamisel, seega pange need systemd-üksusesse või netfilter-persistent tabelisse ja testige pärast taaskäivitust uuesti, sest hilja tõusev tunnel võib need minema pühkida.
Pange tunnel konteineri sisse, kui eesmärk on isolatsioon
Kui üks konteiner peab väljuma kindla sõlme kaudu, käivitage klient selles konteineris. Ta vajab --cap-add NET_ADMIN ja --device /dev/net/tun, ja siis omab ta oma tun0-t, marsruute ja tulemüüri. Kui teised konteinerid läbivad teda, vajab ta ka edastamist ja MASQUERADE-reeglit konteineri sees, ning need partnerid vajavad selget marsruuti või puhverserverit, mis talle osutab; Dockeri vaikimisi sild ei lisa seda marsruuti teie eest.
Hosti võrk, docker run --network host, on odav versioon: konteiner liitub hosti nimeruumiga ja näeb tunneli marsruute otse. See kaotab ka võrguisolatsiooni, kutsub esile pordikonflikte ja on praktikas Linuxi valik. Avaldatud port ei ole asendus. -p 8080:80 teeb teenuse hostist kättesaadavaks; see ei tee sisemisi 10.x aadresse konteineri seest kättesaadavaks, ja nende kahe segamine on viis, kuidas marsruutimisprobleemist saab avatud andmebaasi port.
Eristage nime tõrget kattuvast alavõrgust
Dockeri vaikimisi sild on 172.17.0.0/16 ja paljud ettevõtte VPN-i basseinid asuvad 172.16.0.0/12 sees. Kui tunnel selle vahemiku omab, võib konteinerile mõeldud liiklus selle asemel tunnelisse suunata. Nimed nurjuvad, viga näeb välja nagu DNS, ja probleem on aadressides. Kontrollige sihtkohta, mitte resolverit: ip route get 172.17.0.5 hostil, seejärel võrrelge silla prefiksit VPN-i basseini ja docker network inspect bridge --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'-ga.
Parandus on üks vahemikest liigutada: kas teine vaikimisi aadressibassein Dockerile failis daemon.json või teine bassein koondajal. Veel ühe nimeserveri lisamine ei tee siin midagi, ja ei tee ka ssh -b: kliendi liidesega sidumine muudab lähteaadressi, mitte sihtkoha marsruuti, mis osutab tunnelisse. Kiire tööjaotus: nimi, mis laheneb hostil, kuid mitte konteineris, on resolveri probleem, samas kui otsene IP-ühendus, mis konteineris ripub, kuid hostil töötab, on marsruudi või edastusahela probleem.
WSL ja Docker Desktop ei järgi Linuxi reegleid
Oma vaikimisi NAT-režiimis seisab WSL oma virtuaalse adapteri taga ega saa Windowsi VPN-i sisemisi marsruute ega DNS-järelliiteid, mistõttu brauser töötab ja ping distributsiooni sees mitte. Peegeldatud võrk, mis on saadaval hiljutistes Windows 11 buildides, jagab selle asemel hosti liideseid, kuid see tuleb lubada failis .wslconfig ja distributsioon taaskäivitada käsuga wsl --shutdown. Kinnitage aktiivne režiim käsuga wslinfo --networking-mode enne paranduse rakendamist, sest NAT-i vastus on peegeldatud režiimi jaoks vale ja vastupidi.
Docker Desktop lisab veel ühe kihi. Linuxi konteinerid Windowsis seisavad NAT-i implementatsiooni taga, mida ajalooliselt nimetatakse vpnkit-iks, ja nende tee erineb natiivsest Linuxi hostist. Windowsi konteinerid ühenduvad Hyper-V virtuaallüliti kaudu ja ettevõtte klient võib selle lüliti liikluse blokeerida, seega võivad Linuxi konteinerid samas masinas võrku jõuda, samal ajal kui Windowsi konteineritel pole midagi. Füüsilise adapteriga seotud väline lüliti on tavaline lahendus ja muudab konteineri võrguidentiteeti viisil, mida poliitika ei pruugi lubada.
Enne veel ühe reegli kirjutamist käige neli kihti järjekorras läbi ja peatuge seal, kus üks neist on vale:
- Konteineri sees: kas
ip routejõuab privaatse prefiksini ja kas/etc/resolv.confnimetab upstreami, mis selle lahendab? - Hostil: kas edastamine on sees, kas NAT on seotud tunneli liidesega ja kas edastusahel võtab vastu silla tunnelini?
- Partneril: kas ta teab tagasiteed või loodate NAT-ile, et konteineri alavõrk peita?
- Platvormil: kas WSL on NAT- või peegeldatud režiimis ja kas konteiner on Linux või Windows?
Käivitage iga test uuesti värskes konteineris või kestas. Pikaajaline protsess, millel on vahemällu salvestatud vastus või loodud ühendus, jätkab nurjumist ka pärast seda, kui konfiguratsioon on õige, ja see tõrge näeb täpselt välja nagu parandus, mis ei töötanud.