Izlabojiet Docker un WSL trafiku, kas ignorē resursdatora VPN
Konteineri un WSL patur savus maršrutus, risinātāju un pārsūtīšanas ceļu, tāpēc strādājošs resursdatora tunelis atstāj tos ar novecojušu DNS vai bez izejas. Izlabojiet katru slāni.
Šopavasar lielāko daļu rīta pavadīju, dzenoties pakaļ konteineram, kas nespēja atrisināt nevienu iekšējo vārdu, kamēr blakus esošais pārlūks atvēra viki bez sūdzībām. Tunelis bija uzcelts, pārlūks to pierādīja, un konteiners atradās citā tīkla vārdu telpā ar citu maršrutu tabulu un citu risinātāju. Tālāk ir secība, ko tagad pārbaudu: vispirms maršrutu tabulas, otrkārt vārdu izšķiršana, treškārt pārsūtīšana un visbeidzot resursdatora platforma. Apstājieties pie pirmā soļa, kas jau neizdodas, jo noteikumu pievienošana zemāk stekā slēpj robežu, nevis to pārvieto.
Salīdziniet trīs maršrutu tabulas pirms noteikuma maiņas
Konteinera Docker noklusējuma tiltā ir viens noklusējuma maršruts uz docker0 vārteju, un tam nav ne jausmas, ka tun0 pastāv. Resursdatorā ir tun0, VPN iespiestie maršruti un, iespējams, politikas noteikums, kas pārbaudes trafiku sūta pa citu saskarni, nekā gaidāt. WSL pievieno trešo tabulu aiz sava virtuālā adaptera. Izdrukājiet visas trīs pirms jebkuras rediģēšanas.
| 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 |
Ja vienīgais konteinera maršruts ir tilts un tun0 nekad neparādās tā vārdu telpā, nekas zemāk nepalīdzēs: neviena vārdu servera maiņa neveido maršrutu, un neviens maršruts neveido tuneļa identitāti, ko partneris pieņems. Secība ir svarīga, jo DNS kļūme un maršruta kļūme no čaulas iekšpuses izskatās vienādi.
Novirziet risinātāju uz tuneli, nevis uz publisku
Resursdatorā resolvectl status uzskaita DNS serverus katram savienojumam, un readlink -f /etc/resolv.conf paziņo, vai fails ir systemd stubs, NetworkManager fails vai kaut kas, ko pārrakstījis piegādātāja klients. Konteinera iekšpusē lietotāja definētā tīklā /etc/resolv.conf nosauc 127.0.0.11, Docker iebūvēto risinātāju, kas pārsūta uz to upstream, ar kuru tika konfigurēts dēmons. Savukārt noklusējuma tilta konteiners izveides brīdī saņēma resursdatora faila kopiju un to patur.
Tieši šīs kopijas dēļ tunelis, kas tiek uzcelts pēc konteinera palaišanas, liek konteineram jautāt veco upstream. Vai nu nododiet VPN risinātāju skaidri ar docker run --dns 10.8.0.53, vai iestatiet "dns": ["10.8.0.53"] failā /etc/docker/daemon.json un pārstartējiet dēmonu, vai izveidojiet konteineru no jauna, kad tunelis ir uzcelts. No jauna izveidot parasti ir lētāk nekā atkļūdot risinātāju, kas pirms stundas bija pareizs.
Aizstāšana ar publisku risinātāju ir tas remonts, kas saglabā simptomu. Tas atrisina internetu un neizdodas katrā privātajā zonā, un tas var klusi apiet filtrēšanu, kuras dēļ tunelis pastāv. Ja mēģināsit rakstīt strādājoša konteinera /etc/resolv.conf iekšpusē, gaidiet Device or resource busy: Docker bind-mounto šo failu, tāpēc rediģēšanai vispirms vajag atmontēšanu. --dns iestatīšana izveides laikā ir secība, kas pārdzīvo pārstartēšanu.
Pārsūtiet un tulkojiet, kad konteineri aizņemas tuneli
Ar noklusējuma tiltu resursdators ir maršrutētājs starp docker0 un tun0, un pēc noklusējuma tas neveic nevienu no šiem darbiem. Ieslēdziet pārsūtīšanu un tulkojiet avota adresi, lai partneris redzētu resursdatora tuneļa adresi, nevis to, uz kuru tam nav atgriešanās maršruta (aizstājiet tun0 ar to, kā jūsu klients sauc saskarni):
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 noteikumi ir svarīgi resursdatoros, kuru pārsūtīšanas politika ir DROP. Docker ievieto savas ķēdes, tāpēc pārbaudiet ar paketi, nevis lasot iptables -S: no konteinera, ip route get 10.8.0.20 jānosauc tilta vārteja, un nc -vz 10.8.0.20 443 jāpieslēdzas vai jābeidzas ar taimautu tunelī, nevis risinātājā.
Bez MASQUERADE partnerim vajag atgriešanās maršrutu uz 172.17.0.0/16, ko lielākā daļa attālinātās piekļuves VPN neiespiedīs. Šeit arī plānu salauž uz politiku balstīts klients: ja tas pārtver tikai noteiktu UID vai cgroups trafiku, jūsu pārsūtīšanas noteikumi nekad neredz paketi tuneļa iekšpusē, un labojums pieder klienta maršrutēšanas politikai, nevis iptables. Ar roku pievienotie noteikumi pazūd pārstartēšanā, tāpēc ievietojiet tos systemd vienībā vai netfilter-persistent tabulā un pārbaudiet vēlreiz pēc pārstartēšanas, jo vēlu uzcelts tunelis var tos aizslaucīt.
Ievietojiet tuneli konteinera iekšpusē, ja mērķis ir izolācija
Ja vienam konteineram jāiziet caur noteiktu mezglu, palaidiet klientu tajā konteinerā. Tam vajag --cap-add NET_ADMIN un --device /dev/net/tun, un tad tam ir savs tun0, maršruti un ugunsmūris. Ja citi konteineri iet tam cauri, tam vajag arī pārsūtīšanu un MASQUERADE noteikumu konteinera iekšpusē, un tiem partneriem vajag skaidru maršrutu vai starpnieku, kas norāda uz to; Docker noklusējuma tilts šo maršrutu jūsu vietā nepievieno.
Resursdatora tīkls, docker run --network host, ir lētā versija: konteiners pievienojas resursdatora vārdu telpai un redz tuneļa maršrutus tieši. Tas arī atsakās no tīkla izolācijas, uzaicina portu sadursmes un praksē ir Linux iespēja. Publicēts ports nav aizstājējs. -p 8080:80 padara pakalpojumu sasniedzamu no resursdatora; tas nepadara iekšējās 10.x adreses sasniedzamas no konteinera iekšpuses, un abu sajaukšana ir ceļš, kā maršrutēšanas problēma pārvēršas atklātā datubāzes portā.
Atšķiriet vārda kļūmi no pārklājoša apakštīkla
Docker noklusējuma tilts ir 172.17.0.0/16, un daudzi uzņēmumu VPN baseini atrodas 172.16.0.0/12 iekšpusē. Kad tunelim pieder šis diapazons, konteineram paredzētā trafika var tikt maršrutēta tunelī. Vārdi neizdodas, kļūda izskatās kā DNS, un problēma ir adresēs. Pārbaudiet galamērķi, nevis risinātāju: ip route get 172.17.0.5 resursdatorā, pēc tam salīdziniet tilta prefiksu ar VPN baseinu un ar docker network inspect bridge --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'.
Remonts ir pārvietot vienu no diapazoniem: vai nu citu noklusējuma adrešu baseinu Docker failā daemon.json , vai citu baseinu koncentratorā. Pievienot vēl vienu vārdu serveri šeit neko nedod, un ssh -b arī nē: klienta piesaistīšana saskarnei maina avota adresi, nevis galamērķa maršrutu, kas ved tunelī. Ātrs darba sadalījums: vārds, kas atrisinās resursdatorā, bet ne konteinerā, ir risinātāja problēma, savukārt tiešs IP savienojums, kas karājas konteinerā, bet strādā resursdatorā, ir maršruta vai pārsūtīšanas ķēdes problēma.
WSL un Docker Desktop neievēro Linux noteikumus
Savā noklusējuma NAT režīmā WSL stāv aiz sava virtuālā adaptera un nesaņem Windows VPN iekšējos maršrutus vai DNS sufiksus, tāpēc pārlūks strādā, bet ping izplatīšanas iekšpusē ne. Spoguļota tīklošana, kas pieejama jaunākajās Windows 11 versijās, tā vietā dala resursdatora saskarnes, bet tā ir jāiespējo failā .wslconfig un izplatīšana jāpārstartē ar wsl --shutdown. Apstipriniet aktīvo režīmu ar wslinfo --networking-mode pirms labojuma piemērošanas, jo NAT atbilde ir nepareiza spoguļotajam režīmam un otrādi.
Docker Desktop pievieno vēl vienu slāni. Linux konteineri operētājsistēmā Windows atrodas aiz NAT ieviešanas, ko vēsturiski sauc par vpnkit, un to ceļš atšķiras no vietēja Linux resursdatora. Windows konteineri pieslēdzas caur Hyper-V virtuālo komutatoru, un uzņēmuma klients var bloķēt trafiku no šī komutatora, tāpēc Linux konteineri tajā pašā mašīnā var sasniegt tīklu, kamēr Windows konteineriem nav nekā. Ārējs komutators, kas piesaistīts fiziskajam adapterim, ir ierastais risinājums, un tas maina konteinera tīkla identitāti tādos veidos, kādus politika var nepieļaut.
Pirms rakstāt vēl vienu noteikumu, izstaigājiet četrus slāņus pēc kārtas un apstājieties tur, kur kāds no tiem ir nepareizs:
- Konteinera iekšpusē: vai
ip routesasniedz privāto prefiksu, un vai/etc/resolv.confnosauc upstream, kas to atrisina? - Resursdatorā: vai pārsūtīšana ir ieslēgta, vai NAT ir piesaistīts tuneļa saskarnei, un vai pārsūtīšanas ķēde pieņem tiltu uz tuneli?
- Partnerī: vai tas zina atgriešanās ceļu, vai jūs paļaujaties uz NAT, lai paslēptu konteinera apakštīklu?
- Platformā: vai WSL ir NAT vai spoguļotajā režīmā, un vai konteiners ir Linux vai Windows?
Palaidiet katru testu no jauna svaigā konteinerā vai čaulā. Ilgstošs process ar kešatmiņā saglabātu atbildi vai nodibinātu savienojumu turpinās neizdoties arī pēc tam, kad konfigurācija ir pareiza, un šī kļūme izskatās tieši kā labojums, kas nestrādāja.