Puncte:0

Iptables și docker - dezactivați accesul de la distanță la container păstrând în același timp comunicarea gazdă și containere prin proxy

drapel us

Recent, am început să migrez un server web cu mai multe aplicații pe un server nou și le-am grupat pe fiecare aplicație într-un container docker. Configurația mea actuală constă în nginx pentru proxy invers și servere de baze de date rulează pe serverul însuși și toate aplicațiile web care rulează în propriile lor containere docker.

Acum încerc să securizez serverul web folosind iptables, așa cum făceam cu mulți ani înainte. eu trebuie sa indeplineasca urmatoarele conditii:

  1. Paravanul de protecție normal pentru serviciile non-docker ar trebui să funcționeze în continuare (politicile implicite să renunțe atât pentru intrare, cât și pentru ieșire, doar porturile denumite în mod explicit accesibile)
  2. containerele (cu o singură excepție - vezi mai jos) nu trebuie să fie accesibile din lume
  3. containerele trebuie să poată accesa gazdă folosind „docker.host.internal” pentru a accesa serverele de baze de date
  4. containerele trebuie să poată accesa serviciile altor containere folosind numele lor de domenii publice (proxiate).
  5. un singur container ar trebui să aibă portul 22 accesibil direct din lume (git)

Până acum, am reușit să satisfac doar primele trei cerințe. Configurarea mea simplă pentru iptables, din care am adoptat-o mediul anterior, non-docker, arată cam așa:

# politici implicite de eliminat

-P CĂDERARE INTRARE
-P PĂDURA ÎNTÂMPRE
-P CADEREA IESIRI

# permite navigarea pe internet, NTP, DNS
-A IEȘIRE -p tcp -m tcp --dport 80 -j ACCEPT
-A IEȘIRE -p tcp -m tcp --dport 443 -j ACCEPT
-A INTRARE -p tcp -m tcp --sport 80 -m stare --stare RELATED,ESTABLISHED -j ACCEPT
-A INTRARE -p tcp -m tcp --sport 443 -m stare --stare RELATED,ESTABLISHED -j ACCEPT
-A INTRARE -p udp -m udp --sport 53 -j ACCEPT
-A INTRARE -p tcp -m tcp --sport 53 -j ACCEPT
-A IEȘIRE -p udp -m udp --dport 53 -j ACCEPT
-A IEȘIRE -p tcp -m tcp --dport 53 -j ACCEPT
-A INTRARE -p udp -m udp --dport 123 -j ACCEPT
-A IEȘIRE -p udp -m udp --sport 123 -j ACCEPT

# permit servicii - server web, server SSH pe portul 16 (știu că nu este standard, dar m-am obișnuit cu asta) și SSH pe portul 22 pentru accesarea git
-A INTRARE -p tcp -m tcp --dport 22 -j ACCEPT
-A INTRARE -p tcp -m tcp --dport 16 -j ACCEPT
-A INTRARE -p tcp -m tcp --dport 80 -j ACCEPT
-A INTRARE -p tcp -m tcp --dport 443 -j ACCEPT
-A IEȘIRE -p tcp -m tcp --sport 22 -m stare --stare RELATED,STABLISHED -j ACCEPT
-A IEȘIRE -p tcp -m tcp --sport 16 -m stare --stare RELATED,ESTABLISHED -j ACCEPT
-A IEȘIRE -p tcp -m tcp --sport 80 -m stare --stare RELATED,ESTABLISHED -j ACCEPT
-A IEȘIRE -p tcp -m tcp --sport 443 -m stare --stare RELATED,STABLISHED -j ACCEPT

# permite toată comunicarea locală
-A INTRARE -i lo -j ACCEPT
-A IEȘIRE -o lo -j ACCEPT

# permite ping
-A FORWARD -p icmp -j ACCEPT
-A INTRARE -p icmp -j ACCEPT
-A IEȘIRE -p icmp -j ACCEPT

Nu susțin că acesta este cel mai bun mod de a face lucrurile, dar ar trebui să fie destul de sigur și a funcționat pentru mine de ani de zile.

Acum trec la chestiile pe care nu le înțeleg prea bine. Dacă aplic acest lucru la noua mea configurație docker, se întrerupe accesul la gazdă folosind aliasul „docker.host.internal”. Pentru a permite asta, Obisnuiam:

iptables -A INTRARE -i br-+ -j ACCEPT
iptables -A IEȘIRE -o br-+ -j ACCEPT

Am mai văzut -i docker0 fiind folosit, dar nu a funcționat pentru mine, pentru că fiecare container docker are al lui br-* interfață din configurația mea pe care o folosește pentru a accesa gazda. Aceasta a funcționat, Până acum, bine.

Acum am observat că toate porturile publicate de docker (folosesc 80XX pentru servicii web și apoi domeniile corecte de proxy către acele porturi prin proxy nginx) sunt vizibile din lume. Cu siguranță nu vreau asta, așa că după câteva căutări, am adăugat asta:

iptables -I DOCKER-USER -i venet0 -j DROP

(venet0 este numele interfeței mele de rețea, în loc de eth0)

Acest lucru a funcționat bine, dar au încălcat condițiile 4 și 5 - containerele nu se mai pot accesa unul pe celălalt pe adresa lor de domeniu public și nu mă pot conecta la serverul git prin portul 22 (la care mă așteptam).

Prin comunicare pe adresa de domeniu public, mă refer la următoarele:

Am un server CI de dronă care rulează într-un singur container, expunând portul 8001 către gazdă. Apoi am un proxy nginx care transmite adresa https://ci.example.com spre acest port. Același lucru este valabil și pentru containerul meu Gitea, port expun 8002 și disponibil pe https://git.example.com.

Drona trebuie să se autentifice prin OAuth cu serverul Gitea. Pentru a face acest lucru, trebuie să îl poată accesa prin intermediul https://git.example.com:443 adresa, nu dockerul intern http://gitea_container_name:8002. Am mai multe alte cazuri de utilizare în care acest lucru trebuie să fie posibil, dar acesta explică cel mai bine.

Acum am petrecut multe ore încercând să fac asta să funcționeze, dar fără succes - dacă reușesc să lucrez, alte condiții se întrerup și invers. Unele dintre lucrurile pe care le-am încercat deja (majoritatea provin de la diverse alte întrebări de aici):

# a încercat să activeze un port specific pentru containerul gitea, fără efect
iptables -I DOCKER-USER -i venet0 -p tcp --sport 8002 -j ACCEPT

# a încercat această sugestie, fără efect
iptables -I DOCKER-USER -i venet0 -p tcp -m conntrack --ctorigdstport 443 --ctdir ORIGINAL -j ACCEPT

# fără efect, dar am bănuit că acest lucru nu va funcționa, deoarece nu cred că 443 este ceea ce vine la acest lanț
iptables -I DOCKER-USER -i venet0 -p tcp --dport 443 -j ACCEPT

# fara efect
iptables -A INPUT -i docker0 -j ACCEPT

Este posibilă o astfel de instalare? Poate cineva mai versat în lumea docker și firewall să mă îndrume în direcția corectă?

Configurația mea:

  • Debian 11
  • iptables v1.8.7 (nf_tables)
  • Docker 20.10.5

Multumesc mult anticipat!

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.