Publicarea porturilor Docker față de VPN: unde ajunge răspunsul
Un container publicat răspunde de la propria adresă înainte de NAT-ul invers. Două proiecte pot păstra acel răspuns pe calea publică, cu costuri diferite.
Gazda continuă să răspundă la SSH după ce un VPN cu tunel complet urcă, în timp ce un serviciu publicat prin Docker pe aceeași mașină tace. Nu e nimic în neregulă cu listener-ul: containerul rulează, maparea portului există și pachetul ajunge. Containerul este sănătos, iar cererea chiar îl atinge. Ce diferă este de unde începe răspunsul când Linux își alege ruta, iar această diferență decide care dintre cele două proiecte de mai jos îți trebuie.
Urmează tuplul prin NAT-ul de destinație
Ia o gazdă la 192.0.2.10 care publică TCP 2222 către un container la 172.30.240.5:22. O cerere de la 198.51.100.25 este tradusă înainte de a ajunge la container, iar containerul răspunde ca el însuși.
WAN request: 198.51.100.25 -> 192.0.2.10:2222
after DNAT: 198.51.100.25 -> 172.30.240.5:22
container reply: 172.30.240.5:22 -> 198.51.100.25
La decizia de rutare a gazdei, răspunsul poartă încă adresa sursă a containerului. Traducerea inversă restaurează mai târziu tuplul publicat, și de aceea pachetul pare greșit exact în momentul în care este aleasă ruta.
De ce o regulă doar pentru gazdă îl ratează
O regulă care selectează tabela WAN doar pentru pachetele de la 192.0.2.10 acoperă demonii propriei gazde și ratează complet acest răspuns redirecționat. Adresa sursă din răspuns este 172.30.240.5, nu gazda.
Supracorectarea este să rutezi tot din container prin WAN, ceea ce scutește de VPN și conexiunile de ieșire nelegate ale containerului. Este o politică diferită de cea cerută și de obicei surprinde pe cineva mai târziu.
Potrivirea post-DNAT este un alt hook
Documentația Docker despre firewall-uri observă că filtrarea obișnuită de utilizator vede destinația după DNAT, așa că potrivirea portului publicat 2222 într-o regulă normală nu este același lucru cu potrivirea portului 22 al containerului. Dacă tuplul original contează, folosește mecanismul de destinație originală acceptat în loc să ghicești care port este vizibil.
Această confuzie de hook-uri produce reguli care par corecte și nu se potrivesc niciodată. Verifică contoarele pe regula însăși înainte de a rescrie politica. O regulă fără nicio potrivire îți spune că este evaluată într-un loc în care pachetul nu ajunge niciodată.
Proiectul A: duce decizia ca stare a conexiunii
Un marcaj de conexiune poate duce decizia de intrare prin traducere, dar trebuie restaurat pe pachet înainte de căutarea rutei care contează. Etapele sunt:
- Rezervă un câmp de marcaj și o prioritate de regulă care nu se ciocnesc cu Docker, cu VPN-ul sau cu alt proprietar de politică.
- Identifică doar noua conexiune WAN dorită într-un punct dinainte de DNAT unde urmărirea conexiunilor este disponibilă.
- Înregistrează decizia pe marcajul conexiunii, fără a forța cererea originală în tabela WAN.
- În direcția răspunsului, restaurează doar biții tăi de marcaj pe pachet înainte de rutare.
- Alege o tabelă WAN completă suficient de devreme încât o regulă VPN să nu poată câștiga prima.
Acea tabelă are nevoie de rutele conectate reale și de gateway. Are nevoie și de un comportament definit când ruta lipsește. Căderea silențioasă în tunel este cel mai rău rezultat, pentru că configurația încă pare să funcționeze. În schimb, eșuează închis și înregistrează asta.
Proiectul B: termină pe gazdă
Un frontend configurat deliberat pe partea gazdă, cum ar fi un proxy TCP sau un proxy invers în fața containerului, păstrează răspunsul originat din adresa gazdei. Atunci regulile scrise pentru gazdă se comportă conform așteptărilor, iar containerul rămâne în rețeaua sa privată.
Costul este încă o piesă mobilă cu propria configurație, tratare a adreselor sursă și controale de acces. Este de obicei limita acceptată mai simplă și este adesea răspunsul corect când politica de rutare ar fi întreținută de o singură persoană care ar putea pleca.
Verifică schimbarea, nu intenția
Deschide o conexiune autorizată nouă din partea publică și confirmă că răspunsul iese prin interfața dorită. Apoi verifică dacă o cerere nelegată inițiată de container urmează în continuare VPN-ul.
Nu goli tabela de conexiuni a mașinii pentru a testa o regulă: intrările existente își păstrează maparea anterioară, iar golirea strică tot restul de pe gazdă. Publicarea unui port definește accesibilitatea. Nu definește calea răspunsului. Notează proiectul ales cu numele tabelelor sale, ca următoarea persoană să nu trebuiască să-l redescopere în timpul unui incident.