Këtë pranverë kalova pjesën më të madhe të një mëngjesi duke ndjekur një kontejner që nuk mund të zgjidhte asnjë emër të brendshëm, ndërsa shfletuesi pranë tij hapte wiki-n pa asnjë ankesë. Tuneli ishte lart, shfletuesi e vërtetonte këtë, dhe kontejneri ndodhej në një hapësirë tjetër emrash rrjeti me një tabelë tjetër rrugësh dhe një zgjidhës tjetër. Ajo që vijon është radha që kontrolloj tani: së pari tabelat e rrugëve, së dyti zgjidhja e emrave, së treti përcjellja dhe në fund platforma e hostit. Ndaloni në hapin e parë që tashmë dështon, sepse shtimi i rregullave më poshtë në stivë e fsheh kufirin në vend që ta zhvendosë.

Krahasoni tre tabelat e rrugëve përpara se të ndryshoni një rregull

Një kontejner në urën e parazgjedhur të Docker ka një rrugë të parazgjedhur drejt portës docker0 dhe nuk e di se tun0 ekziston. Hostit i ka tun0, rrugët që shtyu VPN-ja dhe ndoshta një rregull politike që nxjerr trafikun provë përmes një ndërfaqeje tjetër nga ajo që prisni. WSL shton një tabelë të tretë pas përshtatësit të vet virtual. Printoni të treja përpara se të modifikoni ndonjë.

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

Nëse rruga e vetme e kontejnerit është ura dhe tun0 nuk shfaqet kurrë në hapësirën e tij të emrave, asgjë më poshtë nuk do të ndihmojë: asnjë ndryshim i serverit të emrave nuk krijon rrugë, dhe asnjë rrugë nuk krijon identitetin e tunelit që do të pranojë pala. Rradha ka rëndësi sepse një dështim DNS dhe një dështim rruge duken njësoj nga brenda një shell.

Drejtojeni zgjidhësin drejt tunelit në vend të një të publiku

Në host, resolvectl status liston serverat DNS për çdo lidhje, dhe readlink -f /etc/resolv.conf ju tregon nëse skedari është stub i systemd, skedar NetworkManager apo diçka që një klient furnizuesi e ka rishkruar. Brenda një kontejneri në një rrjet të përcaktuar nga përdoruesi, /etc/resolv.conf emërton 127.0.0.11, zgjidhësin e integruar të Docker, i cili përcjell te ai upstream me të cilin u konfigurua demoni. Ndërsa kontejneri në urën e parazgjedhur mori një kopje të skedarit të hostit kur u krijua, dhe e mban atë.

Pikërisht kjo kopje është arsyeja pse një tunel që ngrihet pas nisjes së kontejnerit e lë kontejnerin duke pyetur upstream-in e vjetër. Ose jepni zgjidhësin e VPN-së në mënyrë eksplicite me docker run --dns 10.8.0.53, ose vendosni "dns": ["10.8.0.53"] në /etc/docker/daemon.json dhe rinisni demonin, ose rikrijoni kontejnerin pasi tuneli të jetë lart. Rikrijimi zakonisht kushton më pak se korrigjimi i një zgjidhësi që ishte i saktë një orë më parë.

Zëvendësimi me një zgjidhës publik është rregullimi që e ruan simptomën. Ai e zgjidh internetin dhe dështon në çdo zonë private, dhe mund të anashkalojë në heshtje filtrimin për të cilin ekziston tuneli. Nëse provoni të shkruani brenda /etc/resolv.conf të një kontejneri që punon, prisni Device or resource busy: Docker e monton me bind atë skedar, prandaj redaktimi kërkon fillimisht një çmontim. Vendosja e --dns në krijim është sekuenca që i mbijeton një rinisjeje.

Përcillni dhe përktheni kur kontejnerët marrin hua tunelin

Me urën e parazgjedhur, hosti është një ruter midis docker0 dhe tun0, dhe si parazgjedhje nuk bën asnjërën prej këtyre dy punëve. Aktivizoni përcjelljen dhe përktheni adresën e burimit që pala të shohë një adresë tuneli të hostit në vend të një adrese drejt së cilës nuk ka rrugë kthimi (zëvendësoni tun0 me emrin që klienti juaj i jep ndërfaqes):

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

Rregullat FORWARD kanë rëndësi në hostet, politika e përcjelljes e të cilëve është DROP. Docker fut zinxhirët e vet, prandaj provoni me një paketë në vend që të lexoni iptables -S: nga kontejneri, ip route get 10.8.0.20 duhet të emërtojë portën e urës, dhe nc -vz 10.8.0.20 443 duhet të lidhet ose të skadojë në tunel, jo te zgjidhësi.

Pa MASQUERADE pala ka nevojë për një rrugë kthimi drejt 172.17.0.0/16, të cilën shumica e VPN-ve të aksesit në distancë nuk e shtyjnë. Këtu gjithashtu një klient i bazuar në politika e prish planin: nëse kap vetëm trafikun e UID-ve ose cgroups-ve të caktuara, rregullat tuaja të përcjelljes nuk e shohin kurrë paketën brenda tunelit, dhe rregullimi i takon politikës së rrugëzimit të klientit, jo iptables. Rregullat e shtuara me dorë zhduken në rinisje, prandaj vendosini në një njësi systemd ose në një tabelë netfilter-persistent dhe riprovoni pas një rinisjeje, sepse një tunel që ngrihet vonë mund t'i fshijë ato.

Vendoseni tunelin brenda kontejnerit kur qëllimi është izolimi

Nëse një kontejner duhet të dalë përmes një nyje të caktuar, ekzekutoni klientin në atë kontejner. I duhet --cap-add NET_ADMIN dhe --device /dev/net/tun, dhe atëherë zotëron tun0-n, rrugët dhe murin e vet të zjarrit. Nëse kontejnerë të tjerë kalojnë përmes tij, i duhet gjithashtu përcjellje dhe një rregull MASQUERADE brenda kontejnerit, dhe atyre paleve u duhet një rrugë ose proxy e qartë që tregon drejt tij; ura e parazgjedhur e Docker nuk e shton atë rrugë për ju.

Rrjeti i hostit, docker run --network host, është versioni i lirë: kontejneri i bashkohet hapësirës së emrave të hostit dhe i sheh rrugët e tunelit drejtpërdrejt. Gjithashtu heq dorë nga izolimi i rrjetit, fton përplasje portash dhe në praktikë është një opsion i Linux. Një port i publikuar nuk është zëvendësim. -p 8080:80 e bën një shërbim të arritshëm nga hosti; nuk i bën adresat e brendshme 10.x të arritshme nga brenda kontejnerit, dhe përzierja e të dyjave është mënyra se si një problem rrugëzimi kthehet në një port të ekspozuar të bazës së të dhënave.

Dalloni një dështim emri nga një nënrrjet që mbivendoset

Ura e parazgjedhur e Docker është 172.17.0.0/16, dhe shumë pishina VPN korporative ndodhen brenda 172.16.0.0/12. Sapo tuneli zotëron atë interval, trafiku i destinuar për një kontejner mund të rrugëzohet drejt tunelit. Emrat dështojnë, gabimi duket si DNS, dhe problemi është te adresat. Kontrolloni destinacionin, jo zgjidhësin: ip route get 172.17.0.5 në host, pastaj krahasoni prefiksin e urës me pishinën e VPN-së dhe me docker network inspect bridge --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'.

Rregullimi është të zhvendoset njëri prej intervaleve: ose një pishinë tjetër e parazgjedhur e adresave për Docker në daemon.json ose një pishinë tjetër në koncentrator. Shtimi i një serveri tjetër emrash nuk bën asgjë këtu, dhe as ssh -b nuk bën: lidhja e klientit me një ndërfaqe ndryshon adresën e burimit, jo një rrugë destinacioni që tregon brenda tunelit. Ndarje e shpejtë e punës: një emër që zgjidhet në host por jo në kontejner është problem zgjidhësi, ndërsa një lidhje e drejtpërdrejtë IP që ngec në kontejner por punon në host është problem rruge ose zinxhiri përcjelljeje.

WSL dhe Docker Desktop nuk ndjekin rregullat e Linux

Në modalitetin e vet të parazgjedhur NAT, WSL qëndron pas përshtatësit të vet virtual dhe nuk i merr rrugët e brendshme ose prapashtesat DNS të VPN-së së Windows, prandaj shfletuesi punon dhe ping brenda shpërndarjes jo. Rrjeti pasqyrë, i disponueshëm në ndërtimet e fundit të Windows 11, ndan në vend të kësaj ndërfaqet e hostit, por duhet të aktivizohet në .wslconfig dhe shpërndarja të riniset me wsl --shutdown. Konfirmoni modalitetin aktiv me wslinfo --networking-mode përpara se të aplikoni një rregullim, sepse përgjigja e NAT është e gabuar për modalitetin pasqyrë dhe anasjelltas.

Docker Desktop shton një shtresë tjetër. Kontejnerët Linux në Windows qëndrojnë pas një implementimi NAT që historikisht quhet vpnkit, dhe rruga e tyre ndryshon nga ajo e një hosti Linux të natyrshëm. Kontejnerët Windows lidhen përmes një ndërprerësi virtual Hyper-V, dhe një klient korporativ mund të bllokojë trafikun nga ai ndërprerës, kështu që kontejnerët Linux në të njëjtën makinë mund të arrijnë rrjetin, ndërsa kontejnerët Windows nuk kanë asgjë. Një ndërprerës i jashtëm i lidhur me përshtatësin fizik është zgjidhja e zakonshme, dhe ai ndryshon identitetin e rrjetit të kontejnerit në mënyra që politika mund të mos i lejojë.

Përpara se të shkruani një rregull tjetër, kaloni katër shtresat sipas radhës dhe ndaloni aty ku njëra prej tyre është e gabuar:

  • Brenda kontejnerit: a e arrin ip route prefiksin privat, dhe a emërton /etc/resolv.conf një upstream që e zgjidh atë?
  • Në host: a është aktivizuar përcjellja, a është NAT-i i lidhur me ndërfaqen e tunelit, dhe a e pranon zinxhiri i përcjelljes urën drejt tunelit?
  • Te pala: a e njeh një shteg kthimi, apo po mbështeteni te NAT-i për të fshehur nënrrjetin e kontejnerit?
  • Në platformë: a është WSL në modalitetin NAT apo pasqyrë, dhe a është kontejneri Linux apo Windows?

Ekzekutoni përsëri çdo provë në një kontejner ose shell të re. Një proces afatgjatë me përgjigje të ruajtur në cache ose lidhje të vendosur do të vazhdojë të dështojë pasi konfigurimi të jetë i saktë, dhe ai dështim duket saktësisht si një rregullim që nuk funksionoi.

Artikuj të ngjashëm