De ce un container macvlan nu poate răspunde unui client VPN
Un container macvlan nu poate vorbi cu propriul host, iar răspunsurile lui pot ieși prin gateway-ul greșit. Adăugați o rută shim pe partea hostului și apoi alegeți un model de sursă.
Imaginați-vă un host Linux care termină un VPN și, în același timp, rulează un container într-o rețea macvlan. LAN-ul este 192.168.60.0/24, containerul are 192.168.60.210, iar clienții VPN vin din 10.95.0.0/24. Clientul ajunge la serviciu, răspunsul nu se întoarce niciodată, iar fiecare regulă de firewall de pe host pare corectă. Acest simptom este produs de două constrângeri separate, iar repararea uneia o lasă pe cealaltă la locul ei.
Două constrângeri, un simptom
Prima constrângere este izolarea: driverul macvlan al Docker nu permite unui container să vorbească cu propriul host prin interfața părinte. Traficul dintre stiva hostului și container nu are nicio cale, indiferent cum sunt scrise rutele pe host.
A doua constrângere este calea de întoarcere. Gateway-ul implicit al containerului este de obicei routerul LAN, așa că un răspuns adresat unui client VPN iese prin acel router. Dacă routerul nu are o rută înapoi către pool-ul VPN, răspunsul este aruncat undeva la mijloc.
Cele două defecțiuni arată identic din perspectiva clientului: o cerere care sosește și un răspuns care nu sosește niciodată. Au nevoie de reparații diferite, iar o regulă masquerade largă poate ascunde care dintre ele este încă stricată. De aceea primul test este o captură pe partea containerului, nu încă o modificare a firewallului. Dacă cererea nu apare niciodată acolo, constrângerea de izolare este cea activă.
Construiți shim-ul pe partea hostului, îngust
O a doua interfață macvlan pe host, conectată la același părinte în modul bridge, oferă stivei hostului o identitate proprie în acel segment LAN. Rezervați-i o adresă în afara pool-ului DHCP și în afara intervalului containerului, și rutați doar containerul prin ea.
ip link add macvlan-vpn link eth0 type macvlan mode bridge ip address add 192.168.60.250/32 dev macvlan-vpn ip link set macvlan-vpn up ip route add 192.168.60.210/32 dev macvlan-vpn src 192.168.60.250
Prima comandă creează interfața în modul bridge, care este valoarea implicită documentată pentru acest driver și modul dorit pentru traficul dintre host și container. A doua atribuie un /32 pentru ca adresa să nu intre în conflict cu prefixul LAN, iar a patra trimite prin shim doar adresa containerului.
Nu redirecționați întregul LAN prin interfața nouă. Ruta conectată obișnuită rămâne așa cum este, iar ruta hostului este intenționat îngustă pentru ca un container să câștige o cale fără ca restul segmentului să-și schimbe comportamentul. O rută implicită către shim ar fi alt design cu alte consecințe. Păstrați-o specifică și raza de impact rămâne mică.
Aceste comenzi schimbă configurația de rețea pe un host în funcțiune. Pe un aparat sau o platformă administrată, folosiți mecanismul de configurare acceptat de acea platformă, deoarece o modificare interactivă într-un shell root poate să nu supraviețuiască unei actualizări.
Decideți cum se păstrează sursa
Cu shim-ul la locul lui, containerul poate ajunge la host, iar întrebarea devine ce adresă de sursă poartă răspunsul. Păstrarea sursei VPN originale este modelul mai curat: containerul vede adresa reală a clientului, iar jurnalele și regulile de acces ale serviciului o pot folosi.
Pentru ca asta să funcționeze, configurația de rețea a containerului trebuie să trimită pentru această cale traficul pentru 10.95.0.0/24 către 192.168.60.250 ca gateway al său. Este o setare de rută sau de gateway acceptată în configurația containerului însuși, nu un truc pe partea hostului. Confirmați-o din interiorul containerului în loc să presupuneți că setarea a intrat în vigoare. Un gateway implicit care încă indică routerul LAN va continua să trimită răspunsuri în aceeași gaură.
Dacă designul aprobat ascunde în schimb sursele VPN, limitați traducerea îngust: pool-ul VPN real, shim-ul ca interfață de ieșire și containerul și serviciul concrete.
iptables -t nat -A POSTROUTING -s 10.95.0.0/24 -o macvlan-vpn -j SNAT --to-source 192.168.60.250
Potriviți shim-ul ca interfață de ieșire, nu tunelul. O regulă care numește tunelul interfață de ieșire nu se va potrivi cu un pachet îndreptat spre container, și exact aceasta este greșeala pe care o astfel de configurare o conține de obicei. Păstrați regula la fel de îngustă ca fraza de mai sus și revizuiți-o când se schimbă pool-ul.
Verificați de la client, nu de la host
O cerere de la hostul însuși, legată de adresa shim-ului, demonstrează că shim-ul poate ajunge la container. Nu demonstrează că containerul poate trimite trafic înapoi către o sursă păstrată 10.95.0.x, pentru că adresa de sursă din acel test este cea a shim-ului.
curl -sS --interface 192.168.60.250 -o /dev/null -w '%{http_code}\n' http://192.168.60.210:8080/health
sudo tcpdump -ni macvlan-vpn host 192.168.60.210Prima comandă testează porțiunea de la host la container, iar a doua arată ce trece efectiv prin shim în timp ce un client VPN real face cererea. Uitați-vă la adresa de sursă pe calea de intrare și dacă apare un răspuns cu același flux.
Redirecționarea trebuie activată pe host, iar calea de redirecționare are nevoie de o permisiune pentru pool-ul VPN către shim pe portul serviciului, plus răspunsurile stabilite. O regulă INPUT pe host nu autorizează traficul redirecționat, și acesta este un motiv frecvent pentru care pachetul este aruncat după ce rutarea pare corectă.
Rulați aplicația reală cu credențiale reale, apoi verificați dacă un al doilea serviciu, nelegat, de pe același container vă refuză în continuare. Dacă singura modalitate de a-l face să funcționeze a fost să deschideți fiecare regulă de redirecționare, designul nu este terminat. Notați și ce adresă de sursă a înregistrat serviciul, pentru că pe ea se vor baza propriile reguli de acces de acum înainte.