Traficul containerelor Docker ocolește VPN-ul gazdei: cum verificați
Un VPN al gazdei acoperă doar spațiul de nume de rețea al gazdei. Folosiți aceste verificări pentru a afla dacă traficul containerelor de pe pod intră în tunel sau iese direct.
Browserul de pe gazdă arată adresa de ieșire a VPN-ului, containerul raportează conexiunea de acasă și cineva numește asta scurgere. Nu a scurs nimic. Un tunel al gazdei este un ansamblu de interfețe, rute și reguli care aparțin spațiului de nume de rețea al gazdei, iar un container pe un pod este alt spațiu de nume, cu propria rută implicită. Am stat pe un stack Compose în care clientul VPN era conectat de săptămâni și niciun pachet de container nu intrase vreodată în el.
Verificați spațiul de nume înainte de pictograma din tavă
Spațiile de nume sunt tot argumentul. Când Docker pornește un container pe o rețea de pod, creează un spațiu de nume de rețea, atașează în el un capăt al unei perechi veth și dă acelui spațiu de nume o adresă și o rută implicită. Interfața tunelului, oricum s-ar numi, trăiește în spațiul de nume al gazdei. Traficul din container nu o poate vedea, iar nicio setare a clientului nu schimbă asta din exterior.
Două mișcări acceptate vă scot din izolare. --network host pune containerul în spațiul de nume al gazdei, astfel încât moștenește rutele gazdei și, prin urmare, tunelul. --network container:vpn partajează spațiul de nume al altui container, iar așa trimit majoritatea proiectelor sidecar o încărcare de lucru printr-un container VPN. Ambele sunt alegeri explicite; de obicei doar una dintre ele este cea la care s-a gândit persoana care implementează.
Modul gazdă nu este o actualizare gratuită. Containerul nu mai are adresa lui, publicarea porturilor nu se mai aplică, iar un proces care ține NET_ADMIN acolo poate rescrie rutarea gazdei. Să accepți asta poate fi decizia corectă. Să presupui că este deja activ este felul în care oamenii petrec o seară depanând un tunel care nu a fost niciodată pe traseu.
Urmați pachetul afară din pod
Un container de pe pod își trimite pachetul către poarta implicită, care este interfața podului de pe gazdă. Gazda redirecționează apoi pachetul și, în configurația implicită, traduce adresa sursă în a sa înainte ca pachetul să iasă. Exact acest pas de traducere anulează discret politica.
Când pachetul ajunge la punctul final al tunelului, poartă adresa gazdei. Orice regulă, rută de politică sau decizie de tunel divizat bazată pe adresa originală a containerului nu mai corespunde, iar două containere menite să iasă prin ieșiri diferite nu pot fi deosebite doar după sursă. Dacă aveți nevoie de rutare pe container, decizia trebuie luată înainte de traducere sau într-un spațiu de nume pe care îl controlați.
Docker întreține singur aceste reguli, prin orice backend de firewall cu care a fost configurat demonul. Regulile scrise de mână în afara cârligului acceptat pentru traficul redirecționat, DOCKER-USER, pot fi reordonate sau eliminate când demonul repornește sau gazda se actualizează. documentația Docker despre filtrarea pachetelor arată ordinea lanțurilor; punctul practic este că fiecare regulă are nevoie de un proprietar și de o cale de reîncărcare pe care ați testat-o cu adevărat.
Testați cele două sisteme separat
Dovezile dintr-un spațiu de nume nu spun nimic despre celălalt. O cerere executată în containerul VPN dovedește că tunelul funcționează pentru acel container. Nu este o dovadă despre gazdă, iar aceeași comandă rulată dintr-un container --network host nu este o dovadă despre pod.
# host namespace
ip route get 1.1.1.1
ip -brief addr show
# a fresh container on the same bridge network
docker run --rm --network appnet alpine sh -c 'ip route; cat /etc/resolv.conf; ip -6 route'
Apoi repetați testul în containerul real al aplicației, nu într-o imagine similară. Aplicația poate purta o rută suplimentară, o variabilă de mediu pentru proxy sau un alt resolver, iar fiecare dintre acestea schimbă răspunsul. Verificați rezolvarea numelor și a doua familie de adrese de fiecare dată: containerele de pe podurile definite de utilizator se rezolvă prin resolverul încorporat al Docker la 127.0.0.11, iar o rută implicită IPv6 pe pod poate scoate traficul afară în timp ce sunteți ocupat testând un tunel doar IPv4.
Citiți modelul înainte de a atinge acreditările
Când gazda funcționează și containerul nu, cauza este aproape întotdeauna structurală, iar rotirea cheilor sau reinstalarea clientului pierde o după-amiază. Sortați mai întâi simptomul și remedierea de obicei se numește singură.
| What you see | Usual cause | First check |
|---|---|---|
| Host exits through the VPN, container shows the ISP address | The container never entered the tunnel | Default route inside the container |
| Container works until the daemon restarts, then stops | Rules outside the supported hook, or a changed backend | Daemon's reported firewall backend and DOCKER-USER |
| Container loses internal hosts after the tunnel comes up | VPN prefix overlaps the Docker bridge subnet | ip route on the host, then docker network inspect |
| Small replies arrive, large ones hang | Tunnel MTU or missing MSS clamping | Link MTU on both ends of the tunnel |
| Container falls back to the ISP address when the tunnel drops | Nothing enforces the kill switch for forwarded traffic | Stop the tunnel with a request in flight |
Rândul despre suprapunere merită propria propoziție. Un profil VPN care împinge o rută pentru 172.17.0.0/16, sau pentru un 10.0.0.0/8 care conține din întâmplare prefixul podului dvs., face tunelul să revendice subrețeaua containerelor, iar răspunsurile către adresele traduse vor merge în direcția greșită sau vor dispărea. Renumerotarea rețelei Docker este de obicei mai curată decât acumularea de excepții.
Faceți acoperirea explicită, apoi rupeți-o intenționat
Două proiecte rezistă unei revizuiri. Partajați spațiul de nume al containerului VPN și fiecare încărcare acoperită folosește un singur tunel cu o singură frontieră de repornire, ceea ce este simplu până când un serviciu are nevoie de altă ieșire sau de propria cale DNS. Sau direcționați rețeaua containerelor către o poartă VPN pe gazdă: redirecționarea activată, prefixul podului îndreptat spre tunel, traficul de retur tratat explicit. Asta cumpără control pe rețea și vă costă un set de reguli de întreținut de-a lungul actualizărilor demonului și ale clientului.
În orice caz, testul care contează este cazul de eșec. Opriți tunelul cu o cerere de container în zbor și urmăriți unde merge pachetul. Dacă revine pe calea directă, acoperirea nu a fost niciodată impusă, pentru că un kill switch al clientului guvernează traficul clientului însuși, nu pachetele redirecționate dintr-un pod. Apoi reporniți demonul și gazda și confirmați rezultatul a doua oară; acela este momentul în care regulile scrise de mână dispar.
Înainte de a-l declara terminat, confirmați patru lucruri: interfața tunelului este în același spațiu de nume ca traficul, testul containerului a rulat în containerul real, rezolvarea numelor și ambele familii de adrese au fost verificate, iar testul de eșec al tunelului eșuează în continuare închis. Apoi notați backendul de firewall, versiunea clientului și proprietarul fiecărei reguli. Acea înregistrare este ce împiedică următoarea actualizare să lase un amestec nedocumentat de ipoteze vechi.