Un container care nu ajunge la nimic din spatele VPN-ului corporativ trăiește de obicei într-un spațiu de nume de rețea diferit de cel al tunelului. Rutele, serverele DNS și marcajele firewall ale clientului gazdă aparțin stivei gazdei; un container în rețea punte are a sa. Acest singur fapt explică majoritatea rapoartelor care ajung la o echipă de platformă și este și motivul pentru care „VPN-ul este stricat” și „Docker ocolește VPN-ul” pot fi ambele greșite în același timp. Două configurații foarte diferite se ascund în spatele unui singur simptom, așa că stabiliți pe care o aveți înainte de a schimba vreo setare.

Aflați cui îi aparține spațiul de nume al tunelului

Pe Docker Desktop pentru macOS sau Windows, containerele rulează într-o mașină virtuală Linux. Un client VPN instalat pe desktop creează un tunel în sistemul de operare al desktopului, iar mașina virtuală nu îl vede niciodată. Nicio configurație a containerului nu repară asta, deoarece interfața de care containerul ar avea nevoie nu există deloc în spațiul său de nume de rețea.

Pe un host Linux tunelul trăiește în spațiul de nume al gazdei, iar containerele în punte ajung de obicei la el prin tabelul de rutare al gazdei, cu NAT de sursă aplicat la ieșire. Când acea cale eșuează, cauza este de obicei politica de redirecționare, filtrarea căii inverse sau o subrețea suprapusă, nu o rută lipsă. Confirmați în care dintre cele două lumi vă aflați înainte de a citi mai departe:

docker info --format '{{.OperatingSystem}}'
docker run --rm --net=host alpine ip route | head -5
docker run --rm alpine ip route | head -5

Diferența dintre cele două tabele de rutare este întreaga problemă pe un singur ecran. Dacă vizualizarea gazdei conține interfața tunelului, iar cea a punții nu, priviți izolarea spațiilor de nume, iar tot restul este o alegere despre cum să o traversați.

Rețeaua gazdei este un test, nu un proiect

Rularea unui container cu rețeaua gazdei, pe care Docker o documentează ca partajare a spațiului de nume de rețea al gazdei, îl face să moștenească direct interfața tunelului și rutele acesteia. Dacă aceeași cerere reușește apoi, teoria rutelor este confirmată, iar defecțiunea este izolarea spațiilor de nume, nu acreditările, DNS-ul sau o regulă de acces.

docker run --rm --net=host curl -sS -o /dev/null -w '%{http_code}\n' https://api.internal/health

Păstrați-o ca diagnostic. Rețeaua gazdei renunță la publicarea porturilor și la cea mai mare parte a izolării pe care o doreați de la un container, iar pe Docker Desktop „host” înseamnă mașina virtuală, nu desktopul, așa că un succes sau un eșec acolo vă poate induce în eroare dacă uitați cărei gazde vă adresați.

Un dispozitiv tun și privilegiile care vin cu el

Un client VPN din interiorul containerului are nevoie de un dispozitiv de tunel și de permisiunea de a-l configura. Scurtătura obișnuită este --privileged, care acordă fiecare dispozitiv și relaxează politica de securitate în tot containerul. Este mult mai mult decât cere această sarcină și greu de justificat într-o revizuire.

sudo modprobe tun
docker run --rm -it --device /dev/net/tun --cap-add NET_ADMIN myvpn-client

Forma mai îngustă mapează singurul nod de dispozitiv și adaugă doar capacitatea de administrare a rețelei. Încărcați mai întâi modulul pe gazdă, astfel încât nodul să existe. Dacă containerul pornește și clientul raportează că nu poate deschide dispozitivul de tunel, verificați maparea înainte de a suspecta profilul, pentru că acea eroare este de obicei literală.

Acest design înseamnă și că clientul rulează pentru fiecare container. Este răspunsul corect când fiecare sarcină de lucru are nevoie de propriul tunel, și răspunsul greșit când doreați doar ca tunelul gazdei să fie vizibil, ceea ce echipa de platformă probabil presupunea că faceți.

NAT-ul punții schimbă sursa pe care o vede VPN-ul

Cu puntea implicită, traficul de ieșire al containerului este tradus în adresa gazdei. Prin urmare, în spatele unui VPN partea corporativă vede adresa tunelului gazdei, nu pe cea a containerului, regulile de acces pe sursă se comportă ca și cum gazda ar fi făcut cererea, iar două containere devin imposibil de distins pentru serverul VPN.

macvlan sau ipvlan oferă containerului o adresă LAN, ceea ce ajută la descoperirea în LAN și face containerul să pară un egal pe segment. Ocolește complet și tunelul gazdei, așa că un astfel de container nu va ajunge la prefixe doar-VPN decât dacă VPN-ul este accesibil și din acel LAN.

Ambele forme sunt legitime; răspund la cerințe diferite. Dacă cerința este „acest container trebuie să ajungă la un serviciu doar-VPN”, alegeți între rutarea prin gazdă și terminarea tunelului în interiorul containerului. Notați această alegere înainte de implementare, nu după prima cerere eșuată. Indiferent ce alegeți, înregistrați adresa de sursă pe care o va vedea capătul îndepărtat, pentru că exact aceasta o vor arăta regulile sale de acces și jurnalele sale. Un design care nu poate declara acea adresă nu este terminat.

DNS-ul urmează daemonul, nu tunelul

Un container își primește configurația de resolver la pornire, copiată de la daemon sau din imagine. Adresele pe care VPN-ul le împinge după conectare ajung prea târziu pentru acea copie și sunt împinse către resolverul gazdei, nu în container.

Setați resolverul explicit pentru serviciu sau îndreptați-l către un resolver intern accesibil prin tunel. Un container care rezolvă un nume privat într-o adresă publică folosește de obicei un resolver public, nu suferă de o rută defectă, iar corectarea aparține fișierului compose sau configurației daemonului.

Același raționament se aplică întrebării despre adresa de ieșire. Dacă fiecare container trebuie să apară de la o adresă VPN diferită, un singur tunel al gazdei nu poate livra asta pentru că NAT-ul le restrânge la o singură sursă. Formele viabile sunt un client în spațiul de nume al fiecărui container sau un sidecar care deține tunelul și își partajează stiva, iar ambele schimbă modul în care aplicația este adresată.

Listă de verificare înainte de a închide tichetul: identificați spațiul de nume care deține tunelul, dovediți calea cu rețeaua gazdei, mapați doar dispozitivul tun necesar, rețineți adresa de sursă după NAT, setați resolverul explicit și tratați adresele de ieșire pe container ca o decizie de arhitectură, nu ca un steag.

Articole similare