Осы көктемде таңның көбін ішкі атаудың бірін де шеше алмайтын контейнердің соңынан жүгіруге жұмсадым, ал қасындағы браузер викиді шағымсыз аша берді. Туннель көтерілген, браузер мұны дәлелдеп тұрған, ал контейнер басқа маршрут кестесі мен басқа шешушісі бар өзге желілік атаулар кеңістігінде тұрды. Әрі қарай – қазір тексеретін ретім: әуелі маршрут кестелері, екінші атауды шешу, үшінші жіберу, соңында хост платформасы. Әлдеқашан сәтсіздікке ұшыраған бірінші қадамда тоқтаңыз, себебі стектің төменіне ереже қосу шекараны жылжытудың орнына жасырады.

Ережені өзгертудің алдында үш маршрут кестесін салыстырыңыз

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 кептелісі ме, 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 па?

Әр сынақты жаңа контейнерде немесе қабықта қайта орындаңыз. Кэштелген жауабы немесе орныққан қосылысы бар ұзақ процесс конфигурация дұрыс болғаннан кейін де сәтсіздікке ұшырай береді, және бұл ақау дәл жұмыс істемеген түзетуге ұқсайды.

Қатысты мақалалар