Энэ хавар нэг өглөөний ихэнх хэсгийг дотоод нэрийг нэг ч шийдэж чадахгүй байсан контейнерийн араас мөшгөхөд өнгөрөөсөн бөгөөд хажуудах хөтөч викиг ямар ч гомдолгүй нээж байв. Туннель өргөгдсөн, хөтөч үүнийг баталж байсан ч контейнер өөр маршрутын хүснэгт, өөр шийдэгчтэй өөр сүлжээний нэрийн орон зайд байв. Дараах нь би одоо шалгадаг дараалал юм: эхлээд маршрутын хүснэгтүүд, дараа нь нэрийн шийдэл, гуравдугаарт дамжуулалт, эцэст нь хост платформ. Аль хэдийн бүтэлгүйтсэн эхний алхам дээр зогсоно уу, учир нь стекний доод хэсэгт дүрэм нэмэх нь хилийг зөөхийн оронд нуудаг.

Дүрмийг өөрчлөхөөс өмнө гурван маршрутын хүснэгтийг харьцуулна уу

Docker-ийн анхдагч гүүрэн дээрх контейнер docker0 гарц руу чиглэсэн нэг анхдагч маршруттай бөгөөд tun0 байгааг мэддэггүй. Хостод tun0, VPN-ийн түлхсэн маршрутууд, магадгүй таны хүлээж байснаас өөр интерфейсээр шалгах урсгалыг гаргадаг бодлогын дүрэм байна. WSL өөрийн виртуал адаптерийн ард гурав дахь хүснэгтийг нэмдэг. Аль нэгийг нь засахаас өмнө гурвыг нь хэвлэнэ үү.

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

Хэрэв контейнерийн цорын ганц маршрут нь гүүр бөгөөд tun0 түүний нэрийн орон зайд хэзээ ч гарч ирэхгүй бол доорх юу ч тус болохгүй: нэрийн серверийн өөрчлөлт маршрут үүсгэхгүй, ямар ч маршрут хамтрагчийн хүлээн авах туннелийн таних тэмдгийг үүсгэхгүй. Дараалал чухал, учир нь DNS-ийн алдаа болон маршрутын алдаа бүрхүүлийн дотроос ижил харагдана.

Шийдэгчийг нийтийнх биш туннель рүү чиглүүлнэ үү

Хост дээр, resolvectl status холбоос бүрийн DNS серверүүдийг жагсаадаг бол readlink -f /etc/resolv.conf файл нь systemd stub, NetworkManager файл эсвэл нийлүүлэгчийн клиент дахин бичсэн зүйл эсэхийг хэлнэ. Хэрэглэгчийн тодорхойлсон сүлжээн дэх контейнерийн дотор, /etc/resolv.conf нэрлэнэ 127.0.0.11, Docker-ийн суулгагдсан шийдэгчийг, тэр нь демон тохируулагдсан upstream руу дамжуулна. Харин анхдагч гүүрэн дээрх контейнер үүсэхдээ хост файлын хуулбарыг авч, хадгалдаг.

Тэр хуулбар нь контейнер эхэлсний дараа өргөгдөх туннель контейнерийг хуучин upstream-ээс асуухыг үлдээдэг шалтгаан юм. Нэг бол VPN-ийн шийдэгчийг тодорхойгоор дараах байдлаар дамжуулна уу: docker run --dns 10.8.0.53, эсвэл "dns": ["10.8.0.53"] дотор /etc/docker/daemon.json тохируулаад демоныг дахин эхлүүлнэ үү, эсвэл туннель өргөгдсөний дараа контейнерийг дахин үүсгэнэ үү. Дахин үүсгэх нь ихэвчлэн нэг цагийн өмнө зөв байсан шийдэгчийг дибаг хийхээс хямд.

Нийтийн шийдэгчээр солих нь шинж тэмдгийг хадгалдаг засвар юм. Тэр интернетийг шийддэг ч хувийн бүс бүрт бүтэлгүйтдэг бөгөөд туннель оршин байх шалтгаан болсон шүүлтийг чимээгүй тойрч чадна. Хэрэв ажиллаж буй контейнерийн /etc/resolv.conf дотор бичихийг оролдвол дараахыг хүлээнэ үү: Device or resource busy: Docker тэр файлыг bind-mount хийдэг тул засварт эхлээд салгах шаардлагатай. --dns үүсгэх үед тохируулах нь дахин ачааллыг даван туулдаг дараалал юм.

Контейнерууд туннелийг зээлэх үед дамжуулж, орчуулна уу

Анхдагч гүүртэй үед хост нь docker0 болон tun0 хоорондын маршрутлагч бөгөөд анхдагчаар хоёр ажлыг ч хийдэггүй. Дамжуулалтыг асааж, эх сурвалжийн хаягийг орчуулна уу, ингэснээр хамтрагч буцах маршрутгүй хаягийн оронд хостны туннелийн хаягийг харна (tun0-ийг клиент тань интерфейст өгдөг нэрээр солино уу):

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 дүрмүүд нь дамжуулалтын бодлого DROP байдаг хостод чухал. Docker өөрийн гинжийг оруулдаг тул уншихын оронд пакетаар шалгана уу: iptables -S: контейнероос, ip route get 10.8.0.20 гүүрний гарцыг нэрлэх ёстой бөгөөд nc -vz 10.8.0.20 443 шийдэгч дээр биш, туннель дээр холбогдох эсвэл хугацаа дуусах ёстой.

MASQUERADEгүйгээр хамтрагчид 172.17.0.0/16 руу буцах маршрут хэрэгтэй бөгөөд ихэнх алсын хандалтын VPN үүнийг түлхэхгүй. Энд бодлогод суурилсан клиент төлөвлөгөөг эвддэг: хэрэв тэр зөвхөн тодорхой UID эсвэл cgroups-ийн урсгалыг барьж авбал таны дамжуулалтын дүрмүүд туннелийн доторх пакетыг хэзээ ч хардаггүй бөгөөд засвар нь iptables-д биш, клиентийн маршрутжуулалтын бодлогод хамаарна. Гараар нэмсэн дүрмүүд дахин ачаалахад алга болдог тул тэдгээрийг systemd нэгжид эсвэл netfilter-persistent хүснэгтэд хийгээд дахин ачаалсны дараа дахин шалгана уу, учир нь оройтож өргөгдсөн туннель тэдгээрийг шүүрдэж болно.

Зорилго нь тусгаарлалт бол туннелийг контейнерийн дотор байрлуулна уу

Хэрэв нэг контейнер тодорхой зангилаагаар гарч байх ёстой бол, клиентийг тэр контейнер дотор ажиллуулна уу. Түүнд --cap-add NET_ADMIN болон --device /dev/net/tun хэрэгтэй бөгөөд дараа нь өөрийн tun0, маршрут, галт ханатай болно. Бусад контейнерууд түүгээр дамжин өнгөрвөл түүнд контейнерийн дотор дамжуулалт болон MASQUERADE дүрэм ч хэрэгтэй бөгөөд тэдгээр хамтрагчдад түүн рүү чиглэсэн тодорхой маршрут эсвэл прокси хэрэгтэй; Docker-ийн анхдагч гүүр тэр маршрутыг таны оронд нэмдэггүй.

Хостны сүлжээ, docker run --network host, хямд хувилбар: контейнер хостны нэрийн орон зайд нэгдэж, туннелийн маршрутуудыг шууд харна. Мөн сүлжээний тусгаарлалтыг хаяж, портын мөргөлдөөнийг урьж, бодит байдалд Linux сонголт юм. Нийтэлсэн порт нь орлуулагч биш. -p 8080:80 үйлчилгээг хостноос хүртээмжтэй болгодог; дотоод 10.x хаягуудыг контейнерийн дотроос хүртээмжтэй болгодоггүй бөгөөд хоёрыг хольж хутгах нь маршрутжуулалтын асуудлыг ил гарсан мэдээллийн сангийн порт болгох зам юм.

Нэрийн алдааг давхцаж буй дэд сүлжээнээс ялгана уу

Docker-ийн анхдагч гүүр нь 172.17.0.0/16 бөгөөд олон корпорацийн VPN сан 172.16.0.0/12 дотор байрладаг. Туннель тэр хүрээг эзэмшсэний дараа контейнерт зориулсан урсгал түүний оронд туннель рүү маршрутлагдаж болно. Нэрүүд бүтэлгүйтэж, алдаа DNS шиг харагдах бөгөөд асуудал хаягуудад байна. Очих газрыг шалгана уу, шийдэгчийг биш: ip route get 172.17.0.5 хост дээр, дараа нь гүүрний угтварыг VPN сан болон docker network inspect bridge --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'-тай харьцуулна уу.

Засвар нь хүрээнүүдийн нэгийг зөөх: нэг бол Docker-д зориулсан өөр анхдагч хаягийн сан daemon.json файлд, эсвэл концентратор дээр өөр сан. Энд өөр нэрийн сервер нэмэх нь юу ч хийхгүй, ssh -b ч мөн адил: клиентийг интерфейст уях нь эх сурвалжийн хаягийг өөрчилдөг, туннель рүү чиглэсэн очих маршрутыг биш. Хурдан хөдөлмөрийн хуваарилалт: хост дээр шийдэгддэг ч контейнерт шийдэгддэггүй нэр нь шийдэгчийн асуудал, харин контейнерт гацаж, хост дээр ажилладаг шууд IP холболт нь маршрут эсвэл дамжуулалтын гинжин асуудал юм.

WSL болон Docker Desktop нь Linux-ийн дүрмийг дагадаггүй

Өөрийн анхдагч NAT горимд WSL өөрийн виртуал адаптерийн ард сууж, Windows VPN-ийн дотоод маршрут эсвэл DNS дагаварыг авдаггүй, тиймээс хөтөч ажилладаг бол ping түгээлтийн дотор ажиллахгүй. Сүүлийн үеийн Windows 11 бүтээцэд боломжтой толь сүлжээ нь оронд нь хостны интерфейсүүдийг хуваалцдаг боловч үүнийг .wslconfig дотор идэвхжүүлж, түгээлтийг wsl --shutdown командаар дахин эхлүүлэх ёстой. Идэвхтэй горимыг wslinfo --networking-mode командаар засварыг хэрэглэхээс өмнө баталгаажуулна уу, учир нь NAT-ийн хариулт толь горимд буруу бөгөөд эсрэгээрээ.

Docker Desktop дахин нэг давхарга нэмдэг. Windows дээрх Linux контейнерууд түүхэн vpnkit гэж нэрлэгддэг NAT хэрэгжилтийн ард суудаг бөгөөд тэдний зам эх Linux хостоос ялгаатай. Windows контейнерууд Hyper-V виртуал коммутатороор холбогдож, корпорацийн клиент тэр коммутаторын урсгалыг хааж болох тул нэг машин дээрх Linux контейнерууд сүлжээнд хүрч чадах бол Windows контейнеруудад юу ч байхгүй. Физик адаптерт уясан гадаад коммутатор нь ердийн шийдэл бөгөөд контейнерийн сүлжээний таних тэмдгийг бодлого зөвшөөрөхгүй байж болох аргаар өөрчилдөг.

Өөр дүрэм бичихээс өмнө дөрвөн давхаргыг дарааллаар нь туулж, аль нь буруу байгаа тэнд зогсоно уу:

  • Контейнерийн дотор: ip route хувийн угтварт хүрч байна уу, мөн /etc/resolv.conf түүнийг шийддэг upstream-ийг нэрлэж байна уу?
  • Хост дээр: дамжуулалт асаалттай юу, NAT нь туннелийн интерфейст уясан уу, дамжуулалтын гинж гүүрээс туннель рүү зөвшөөрч байна уу?
  • Хамтрагч дээр: тэр буцах замыг мэдэх үү, эсвэл контейнерийн дэд сүлжээг нуухын тулд NAT-д найдаж байна уу?
  • Платформ дээр: WSL NAT эсвэл толь горимд байна уу, контейнер нь Linux эсвэл Windows уу?

Тест бүрийг шинэ контейнер эсвэл бүрхүүлд дахин ажиллуулна уу. Кэшлэсэн хариулт эсвэл тогтоосон холболттой урт хугацааны процесс тохиргоо зөв болсны дараа ч бүтэлгүйтсээр байх бөгөөд тэр алдаа нь ажиллаагүй засвартай яг адилхан харагдана.

Холбоотой нийтлэлүүд