Хосттун VPN'ин этибарга албаган Docker жана WSL трафигин оңдогула
Контейнерлер жана WSL өз маршруттарын, чечүүчүсүн жана өткөрүү жолун сакташат, ошондуктан иштеп турган хост туннели аларды эски DNS менен же чыгуу жолу жок калтырат. Ар бир катмарды оңдогула.
Бул жазда эртеңтин көп бөлүгүн ички аттын бирин да чече албаган контейнердин артынан кууп өткөрдүм, ал эми жанындагы браузер викини нааразылыксыз ачып жаткан. Туннель көтөрүлгөн, браузер муну далилдеп турган, ал эми контейнер башка маршрут таблицасы жана башка чечүүчүсү бар башка тармактык аттар мейкиндигинде турган. Кийинкиси – азыр текшерип жаткан тартибим: адегенде маршрут таблицалары, экинчи аттарды чечүү, үчүнчү өткөрүү жана акырында хост платформасы. Мурунтан эле ишке ашпаган биринчи кадамда токтогула, анткени стектин төмөнүрөөк бөлүгүнө эреже кошуу чекти жылдыруунун ордуна жашырат.
Эрежени өзгөртүүнүн алдында үч маршрут таблицасын салыштыргыла
Docker'дин демейки көпүрөсүндөгү контейнердин docker0 дарбазасына багытталган бир демейки маршруту бар жана tun0 бар экенин билбейт. Хостто tun0, VPN түрткөн маршруттар жана, балким, сыноо трафигин күткөндөн башка интерфейс менен чыгарган саясат эрежеси бар. WSL өзүнүн виртуалдык адаптеринин артына үчүнчү таблицаны кошот. Кайсынысын болбосун оңдоодон мурун үчөөнү тең басып чыгаргыла.
| 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 |
Эгер контейнердин жалгыз маршруту көпүрө болуп, 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 ACCEPTFORWARD эрежелери өткөрүү саясаты 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'бу?
Ар бир сыноону жаңы контейнерде же кабыкта кайра иштеткиле. Кэштелген жообу же түзүлгөн байланышы бар узак процесс конфигурация туура болгондон кийин да ишке ашпай жатат, жана ал бузулуш так иштебеген оңдоого окшош.