Bu bahorda ertalabning koʻp qismini bitta ham ichki nomni hal qila olmagan konteyner ortidan quvib oʻtkazdim, yonidagi brauzer esa hech qanday shikoyatsiz vikini ochib turardi. Tunnel koʻtarilgan edi, brauzer buni isbotlayotgan edi, konteyner esa boshqa marshrut jadvali va boshqa rezolverga ega boshqa tarmoq nom fazosida turardi. Keyingi — hozir tekshiradigan tartibim: avval marshrut jadvallari, keyin nomlarni hal qilish, soʻngra yoʻnaltirish va oxirida host platformasi. Allaqachon yiqilayotgan birinchi qadamda toʻxtang, chunki stekning pastiga qoida qoʻshish chegarani koʻchirish oʻrniga yashiradi.

Qoidani oʻzgartirishdan oldin uchta marshrut jadvalini solishtiring

Docker'ning standart koʻprigidagi konteyner docker0 darvozasiga boradigan bitta standart marshrutga ega va tun0 borligini bilmaydi. Hostda tun0, VPN itarib yuborgan marshrutlar va, ehtimol, sinov trafigini siz kutgandan boshqa interfeys orqali chiqaradigan siyosat qoidasi bor. WSL oʻzining virtual adapteri ortiga uchinchi jadvalni qoʻshadi. Birortasini tahrirlashdan oldin uchtasini ham chop eting.

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

Agar konteynerning yagona marshruti koʻprik boʻlsa va tun0 uning nom fazosida hech qachon koʻrinmasa, pastdagi hech narsa yordam bermaydi: hech qanday nom serveri oʻzgarishi marshrut yaratmaydi va hech qanday marshrut sherik qabul qiladigan tunnel identifikatorini yaratmaydi. Tartib muhim, chunki qobiq ichidan DNS nosozligi ham, marshrut nosozligi ham bir xil koʻrinadi.

Rezolverni umumiyga emas, tunnelga qarating

Hostda, resolvectl status har bir ulanish uchun DNS serverlarini sanaydi, va readlink -f /etc/resolv.conf fayl systemd stubmi, NetworkManager faylimi yoki sotuvchi mijoz qayta yozgan narsami — shuni aytadi. Foydalanuvchi belgilagan tarmoqdagi konteyner ichida, /etc/resolv.conf nomlaydi 127.0.0.11, Docker'ning ichki rezolverini, u daemon sozlangan upstreamga yoʻnaltiradi. Standart koʻprikdagi konteyner esa yaratilganda host faylining nusxasini olgan va uni saqlab turadi.

Aynan shu nusxa konteyner ishga tushgandan keyin koʻtarilgan tunnel konteynerni eski upstreamdan soʻrab qoldirishining sababi. Yoki VPN rezolverni ochiq ravishda shu bilan uzating docker run --dns 10.8.0.53, yoki "dns": ["10.8.0.53"] ichida /etc/docker/daemon.json belgilab daemonni qayta ishga tushiring, yoki tunnel koʻtarilgach konteynerni qaytadan yarating. Qayta yaratish odatda bir soat oldin toʻgʻri boʻlgan rezolverni disk raskadrovka qilishdan arzon.

Umumiy rezolver qoʻyish — simptomni saqlab qoladigan tuzatish. U internetni hal qiladi, lekin har bir xususiy zonada yiqiladi va tunnel mavjud boʻlgan filtrlashni jimgina chetlab oʻtishi mumkin. Ishlab turgan konteynerning /etc/resolv.conf ichiga yozishga urinsangiz, kuting Device or resource busy: Docker u faylni bind-mount qiladi, shuning uchun tahrirlash avval unmount talab qiladi. --dns yaratish paytida belgilash qayta ishga tushishdan omon qoladigan tartib.

Konteynerlar tunnelni qarzga olganda yoʻnaltiring va tarjima qiling

Standart koʻprik bilan host docker0 va tun0 orasidagi router boʻlib, standart holatda ikkala ishni ham qilmaydi. Yoʻnaltirishni yoqing va manba manzilini tarjima qiling, shunda sherik qaytish marshruti yoʻq manzil oʻrniga hostning tunnel manzilini koʻradi (tun0 ni mijozingiz interfeysga bergan nom bilan almashtiring):

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 qoidalari yoʻnaltirish siyosati DROP boʻlgan hostlarda muhim. Docker oʻz zanjirlarini kiritadi, shuning uchun oʻqish oʻrniga paket bilan sinab koʻring iptables -S: konteynerdan, ip route get 10.8.0.20 koʻprik darvozasini nomlashi kerak, va nc -vz 10.8.0.20 443 rezolverda emas, tunnelda ulanashi yoki vaqti tugashi kerak.

MASQUERADE boʻlmasa sherikka 172.17.0.0/16 ga qaytish marshruti kerak, uni koʻp masofaviy kirish VPN'lari itarib yubormaydi. Bu yerda siyosatga asoslangan mijoz ham rejani buzadi: agar u faqat muayyan UID yoki cgroups trafigini tutsa, sizning yoʻnaltirish qoidalaringiz tunnel ichidagi paketni hech qachon koʻrmaydi va tuzatish iptables'da emas, mijozning marshrutlash siyosatida boʻladi. Qoʻlda qoʻshilgan qoidalar qayta yuklashda yoʻqoladi, shuning uchun ularni systemd birligiga yoki netfilter-persistent jadvaliga joylang va qayta yuklashdan keyin yana sinab koʻring, chunki kech koʻtarilgan tunnel ularni supurib tashlashi mumkin.

Maqsad izolyatsiya boʻlsa tunnelni konteyner ichiga joylashtiring

Agar bitta konteyner muayyan tugun orqali chiqishi kerak boʻlsa, mijozni shu konteynerda ishga tushiring. Unga --cap-add NET_ADMIN va --device /dev/net/tun kerak, shundan keyin uning oʻz tun0 i, marshrutlari va xavfsizlik devori boʻladi. Agar boshqa konteynerlar undan oʻtsa, unga konteyner ichida yoʻnaltirish va MASQUERADE qoidasi ham kerak, va oʻsha sheriklarga unga qaragan aniq marshrut yoki proksi kerak; Docker'ning standart koʻprigi bu marshrutni siz uchun qoʻshmaydi.

Host tarmogʻi, docker run --network host, arzon variant: konteyner hostning nom fazosiga qoʻshiladi va tunnel marshrutlarini toʻgʻridan-toʻgʻri koʻradi. Lekin u tarmoq izolyatsiyasidan voz kechadi, port toʻqnashuvlarini chaqiradi va amalda Linux varianti hisoblanadi. E'lon qilingan port uning oʻrnini bosmaydi. -p 8080:80 xizmatni hostdan yetib boradigan qiladi; ichki 10.x manzillarni konteyner ichidan yetib boradigan qilmaydi va ikkalasini aralashtirish marshrutlash muammosini ochiq ma'lumotlar bazasi portiga aylantirish yoʻlidir.

Nom nosozligini ustma-ust tushgan subnetdan ajrating

Docker'ning standart koʻprigi 172.17.0.0/16, va koʻp korporativ VPN hovuzlari 172.16.0.0/12 ichida yotadi. Tunnel oʻsha diapazonga ega boʻlgach, konteynerga moʻljallangan trafik uning oʻrniga tunnelga yoʻnaltirilishi mumkin. Nomlar yiqiladi, xato DNS ga oʻxshaydi va muammo manzillarda. Manzilni tekshiring, rezolverni emas: ip route get 172.17.0.5 hostda, keyin koʻprik prefiksini VPN hovuzi va docker network inspect bridge --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}' bilan solishtiring.

Tuzatish — diapazonlardan birini koʻchirish: yoki daemon.json da Docker uchun boshqa standart manzil hovuzi, yoki konsentratorda boshqa hovuz. Bu yerda yana bitta nom serveri qoʻshish hech narsa qilmaydi, ssh -b ham qilmaydi: mijozni interfeysga bogʻlash manba manzilini oʻzgartiradi, tunnelga qaragan manzil marshrutini emas. Tez ish taqsimoti: hostda hal boʻladigan, lekin konteynerda hal boʻlmaydigan nom rezolver muammosi, konteynerda osilib qoladigan, lekin hostda ishlaydigan toʻgʻridan-toʻgʻri IP ulanish esa marshrut yoki yoʻnaltirish zanjiri muammosi.

WSL va Docker Desktop Linux qoidalariga rioya qilmaydi

Oʻzining standart NAT rejimida WSL oʻz virtual adapteri ortida oʻtiradi va Windows VPN'ning ichki marshrutlari yoki DNS suffikslarini olmaydi, shuning uchun brauzer ishlaydi, ping esa distributiv ichida ishlamaydi. Soʻnggi Windows 11 buildlarida mavjud oynali tarmoq esa host interfeyslarini boʻlishadi, lekin uni .wslconfig da yoqish va distributivni wsl --shutdown bilan qayta ishga tushirish kerak. Faol rejimni wslinfo --networking-mode bilan tasdiqlang, tuzatish qoʻllashdan oldin, chunki NAT javobi oynali rejim uchun xato va aksincha.

Docker Desktop yana bir qatlam qoʻshadi. Windows'dagi Linux konteynerlar tarixan vpnkit deb atalgan NAT amalga oshirilishi ortida oʻtiradi va ularning yoʻli mahalliy Linux hostdan farq qiladi. Windows konteynerlar Hyper-V virtual kaliti orqali ulanadi va korporativ mijoz oʻsha kalitdan kelayotgan trafikni bloklashi mumkin, shuning uchun bir xil mashinadagi Linux konteynerlar tarmoqqa yetib borishi mumkin, Windows konteynerlarda esa hech narsa yoʻq. Jismoniy adapterga bogʻlangan tashqi kalit odatiy yechim boʻlib, u konteynerning tarmoq identifikatorini siyosat ruxsat bermasligi mumkin boʻlgan usullarda oʻzgartiradi.

Yana bir qoida yozishdan oldin toʻrt qatlamni tartib bilan bosib oʻting va qaysi biri xato boʻlsa, oʻsha yerda toʻxtang:

  • Konteyner ichida: ip route xususiy prefiksga yetib boradimi va /etc/resolv.conf uni hal qiladigan upstreamni nomlaydimi?
  • Hostda: yoʻnaltirish yoqilganmi, NAT tunnel interfeysiga bogʻlanganmi va yoʻnaltirish zanjiri koʻprikdan tunnelga ruxsat beradimi?
  • Sherikda: u qaytish yoʻlini biladimi yoki siz konteyner subnetini yashirish uchun NAT ga tayanayapsizmi?
  • Platformada: WSL NAT yoki oynali rejimdami va konteyner Linux yoki Windowsmi?

Har bir sinovni yangi konteyner yoki qobiqda qayta ishga tushiring. Keshlangan javobi yoki oʻrnatilgan ulanishi boʻlgan uzoq muddatli jarayon konfiguratsiya toʻgʻri boʻlgandan keyin ham yiqilaveradi va bu nosozlik ishlamagan tuzatishga aynan oʻxshaydi.

O'xshash maqolalar