Spații de nume de rețea Linux pentru un VPN: ce nu izolează
Un spațiu de nume mută interfețe, rute și socketuri, nu fișiere sau conturi. Iată ce acoperă un VPN în propriul netns și pe unde traficul încă scapă.
Porniți VPN-ul în propriul spațiu de nume, rulați acolo o aplicație, iar traficul iese totuși pe ruta gazdei. Nimic nu este stricat: spațiul de nume guvernează doar procesele care intră în el, iar scurgerea a venit de la unul care nu a intrat niciodată. Interfețele, adresele, rutele, regulile de firewall și socketurile sunt ceea ce deține spațiul de nume. Fișierele, conturile și serviciile deja în execuție nu sunt, și de aici vin majoritatea surprizelor.
Ce deține spațiul de nume și unde se naște socketul
Mutați o interfață într-un spațiu de nume și gazda o pierde; construiți un tunel înăuntru și gazda nu îl poate vedea. Acesta este mecanismul unui VPN limitat la un spațiu de nume: dispozitivul și rutele către el trăiesc într-un context pe care doar procesele alese îl ating. Gazda își păstrează ruta implicită, așa că tot ce este afară rămâne neatins.
Pentru WireGuard, contextul creării contează la fel de mult ca locația actuală: socketul UDP este legat în spațiul de nume în care a fost creată interfața, chiar și după ce dispozitivul se mută altundeva. De care tabelă de rutare depind pachetele criptate depinde de acel loc de naștere. Când socketul rămâne într-un context fără rută către peer, interfața interoghează și strângerea de mână nu iese niciodată. Verificați locul nașterii, apoi locația actuală.
Ce nu izolează un spațiu de nume
Nimic de aici nu separă sisteme de fișiere, conturi sau secrete, și niciuna dintre aceste granițe nu apare pentru că ați creat un spațiu de nume. Configurația resolverului este un fișier, așa că un proces din interior poate citi în continuare o setare care indică resolverul gazdei și își poate trimite interogarea pe ruta pe care aceasta o implică. O aplicație care predă cererea unui intermediar sau serviciu de sistem deja în execuție implică un proces într-un context complet diferit. Ambele sunt cereri la care granița nu a fost niciodată menită să răspundă.
Soluția este un fișier pentru fiecare spațiu de nume în /etc/netns/<name>/resolv.conf, sau un bind mount al unui fișier pregătit, îndreptat către un resolver accesibil din interior. Editarea /etc/resolv.conf pe gazdă nu schimbă nimic din ce vede spațiul de nume.
Amplasarea proceselor este controlul
Izolarea pe care o obțineți este exact izolarea proceselor pe care le porniți în interior. Un shell pornit prin ajutorul exec al spațiului de nume, și tot ce generează, rămâne înăuntru; o aplicație desktop lansată din sesiunea gazdei nu. Creați contextul, mutați dispozitivul, apoi demonstrați ambele părți:
ip netns add vpn1
ip link set wg0 netns vpn1
ip netns exec vpn1 wg show
wg show
Citiți primul wg show din interiorul spațiului de nume și al doilea de pe gazdă, și așteptați-vă ca doar unul dintre ele să listeze peerul. Dacă ambele o fac, dispozitivul nu s-a mișcat niciodată; dacă niciunul, a plecat altundeva. Când lansatorul este un manager de servicii, fișierul unit este cel care trebuie editat, nu scurtătura de pe desktop. O unitate fără setarea spațiului de nume pornește demonul în contextul gazdei și anulează în tăcere proiectul.
Testați din contextul aplicației
Rulați verificarea cu același binar și același utilizator pe care le folosește aplicația, în interiorul spațiului de nume. Includeți DNS și ambele familii de adrese, pentru că o rută IPv6 la care nu v-ați gândit niciodată este o ieșire obișnuită. Un test din propriul shell dovedește doar că shellul dumneavoastră este izolat.
Apoi rulați verificarea identică pe gazdă și confirmați că răspunsurile diferă: adresa tunelului și ieșirea dorită înăuntru, ruta gazdei și ieșirea biroului afară, și resolverul după nume. Numiți spațiile de nume după implementare, nu după protocol, ca un script de curățare să nu confunde două dintre ele.
Redirecționare, politică de eșec și curățare
Pentru o poartă, activați redirecționarea în mod deliberat și decideți ce trebuie să se întâmple când tunelul cade. Un spațiu de nume nu blochează rutele pe care le instalați în el, așa că o rută de rezervă către gazdă va fi folosită dacă creați una. Este o decizie de politică și ar trebui scrisă înainte ca o pană să o testeze.
Notați numele spațiilor de nume, interfețele și cine deține configurația, ca curățarea să elimine doar ce a creat implementarea. Resetarea rețelei gazdei în timpul unei reveniri transformă curățarea într-o pană. Pagina network_namespaces(7) este scurtă și merită citită înainte de a proiecta acel drum.