Wpis techniczny
Docker i dynamiczny firewall: jak żyją reguły po publikacji portów
Reguły Dockera pojawiają się i znikają razem z kontenerami. To zmienia audyt bezpieczeństwa, utrudnia kontrolę ekspozycji usług i wymaga patrzenia na runtime, nie tylko na konfigurację.
W poprzednim wpisie opisałem, dlaczego publikacja portów przez Dockera potrafi ominąć systemowy firewall. Tym razem skoncentruję się na mniej oczywistym elemencie: na tym, jak te reguły zachowują się w czasie.
To właśnie tutaj Docker najmocniej odchodzi od klasycznego modelu pracy z firewallem.
Seria: Docker i firewall
- Mechanizm: dlaczego publikacja portów może ominąć firewall
- Runtime: jak reguły pojawiają się i znikają razem z kontenerami
- Praktyka: jak odzyskać kontrolę nad ekspozycją usług
Firewall, który żyje razem z kontenerami
W tradycyjnym podejściu konfigurujesz firewall, zapisujesz reguły i traktujesz je jako dość stabilny element systemu. Możesz je audytować, porównywać i utrzymywać jako świadomą politykę dostępu.
Docker działa inaczej. Gdy publikujesz port kontenera, reguły nie są tylko trwałą konfiguracją hosta. Stają się częścią bieżącego stanu runtime.
Przykład:
docker run -d -p 8080:80 nginx
Po uruchomieniu kontenera reguły pojawiają się natychmiast, a port zaczyna być osiągalny.
Kiedy zatrzymasz kontener:
docker stop <container>
reguły znikają razem z nim, a wystawiony port przestaje istnieć.
W praktyce oznacza to prostą zmianę modelu: firewall przestaje być wyłącznie konfiguracją i zaczyna być efektem ubocznym działania kontenerów.
Dlaczego to komplikuje pracę operacyjną
Sam fakt, że reguły są dynamiczne, nie musi jeszcze być problemem. Problem zaczyna się wtedy, gdy próbujesz na tej podstawie prowadzić audyt, kontrolować ekspozycję usług albo zbudować przewidywalny standard pracy zespołu.
Audyt pokazuje tylko chwilowy stan
Polecenie:
ufw status
nie daje pełnego obrazu sytuacji.
Nawet jeśli sprawdzisz bezpośrednio iptables:
iptables -t nat -L -n
to nadal widzisz tylko snapshot z konkretnego momentu. Jeżeli kontenery są regularnie uruchamiane, restartowane albo usuwane, taki odczyt szybko przestaje być aktualny.
Każde docker run -p może wystawić usługę na świat
W środowisku zespołowym to szczególnie istotne. Jedno polecenie uruchomienia kontenera może w praktyce oznaczać natychmiastową zmianę ekspozycji usługi.
Jeżeli nie ma centralnej warstwy wejściowej ani prostych zasad, publikacja portów staje się rozproszona. To zwykle kończy się tym, że nikt nie ma pełnego obrazu, co naprawdę jest dostępne z zewnątrz.
Trudno wskazać jedno źródło prawdy
W modelu deklaratywnym oczekujesz jednego miejsca, które opisuje stan systemu. Przy Dockerze część tego stanu żyje po prostu w runtime.
To oznacza, że pełny obraz wymaga jednoczesnego spojrzenia na:
- konfigurację hosta
- aktualny stan kontenerów
- sposób publikacji portów
Lepszy model mentalny
Żeby ograniczyć pomyłki, warto przyjąć kilka prostych założeń.
Kontener to także zmiana polityki ruchu
Uruchomienie kontenera z -p nie jest wyłącznie wdrożeniem aplikacji. To równocześnie zmiana sposobu, w jaki host obsługuje ruch przychodzący.
-p to publikacja, nie zwykłe mapowanie
To drobna różnica językowa, ale praktycznie bardzo użyteczna. Jeśli myślisz o -p jako o publikacji usługi, łatwiej wychwycić skutki bezpieczeństwa niż wtedy, gdy traktujesz to tylko jako techniczne mapowanie portu.
Najpierw patrz na runtime
Jeżeli chcesz wiedzieć, co faktycznie jest wystawione, zacznij od sprawdzenia bieżącego stanu kontenerów:
docker ps --format "table {{.Names}}\t{{.Ports}}"
To często daje bardziej użyteczny obraz niż sama analiza konfiguracji firewalla bez kontekstu uruchomionych usług.
Rootless nie usuwa całego problemu
Rootless Docker nie ingeruje w hostowe iptables, więc odpada część problemów związanych z ukrytymi zmianami w firewallu. Nie znika jednak sam temat ekspozycji usług.
Zmienia się mechanizm, ale nadal trzeba wiedzieć:
- które usługi są publikowane
- na jakich interfejsach
- kto w zespole może to robić
Rootless poprawia przewidywalność, ale nie zastępuje sensownych zasad operacyjnych.
Jak odzyskać kontrolę
Najlepiej działa ograniczenie liczby miejsc, w których w ogóle może dojść do publikacji portu.
Ogranicz bezpośrednie -p
Jeżeli nie ma wyraźnej potrzeby, trzymaj usługi w sieci wewnętrznej Dockera i wystawiaj ruch przez jedną warstwę wejściową, na przykład reverse proxy.
Ustal prosty standard zespołowy
W praktyce wystarczy kilka zasad:
-ptylko dla usług brzegowych- pozostałe usługi bez bezpośredniej publikacji portów
- jedna kontrolowana warstwa ingressu
Monitoruj runtime
Nawet przy dobrych zasadach warto regularnie sprawdzać, co faktycznie działa:
docker ps --format "table {{.Names}}\t{{.Ports}}"
To prosty nawyk, ale bardzo skuteczny.
Wniosek
Docker nie tylko zmienia reguły firewalla. On sprawia też, że ich obecność zależy od bieżącego stanu kontenerów.
Właśnie dlatego bezpieczeństwa nie da się tu ocenić wyłącznie na podstawie statycznej konfiguracji hosta. Trzeba patrzeć również na runtime i traktować publikację portów jako świadomą decyzję architektoniczną.
Jeżeli chcesz dobrze zrozumieć sam mechanizm dodawania reguł, wróć też do artykułu o tym, dlaczego porty Dockera omijają systemowy firewall.