Firewalld w Rocky i AlmaLinux: konfiguracja krok po kroku
Poznaj podstawy konfiguracji firewalld w systemach Rocky oraz AlmaLinux. Dowiedz się, jak otwierać porty SSH i HTTP, unikać błędu --permanent oraz zarządzać strefami sieciowymi.
Czym jest firewalld i dlaczego Rocky oraz AlmaLinux go dostarczają
firewalld to menedżer zapory sieciowej instalowany domyślnie w systemach Rocky Linux, AlmaLinux oraz innych dystrybucjach bazujących na Red Hat Enterprise Linux (RHEL). Narzędzie to nie dokonuje samodzielnej inspekcji pakietów. Przechowuje zapisaną konfigurację i przekształca ją w reguły nftables. Jedno polecenie, firewall-cmd, pozwala na edycję konfiguracji bez przerywania pracy serwera.
Osoby znające zasadę działania ufw w systemie Ubuntu VPS wiedzą, na czym polega to zadanie. firewalld wprowadza dwa pojęcia, których nie posiada ufw. Pierwszym z nich są strefy: nazwane polityki, do których przypisywane są pakiety. Drugim jest podział na reguły działające w czasie rzeczywistym oraz reguły zapisane, co realizowane jest za pomocą flagi --permanent i stanowi najczęstsze źródło nieporozumień związanych z tym narzędziem.
Wszystkie poniższe polecenia należy uruchomić na własnym serwerze. Każda zmiana powinna być testowana z poziomu drugiego urządzenia, ponieważ reguła poprawna lokalnie może być błędna z perspektywy sieci zewnętrznej.
Otwórz SSH przed wykonaniem jakichkolwiek innych działań
Większość instalacji Rocky Linux oraz AlmaLinux posiada domyślnie zainstalowany i uruchomiony firewalld, a dostarczona konfiguracja zezwala na połączenia SSH. Niektóre minimalne obrazy chmurowe nie zawierają tego pakietu. Należy to sprawdzić, zamiast zakładać, że tak jest.
sudo dnf install -y firewalld
sudo systemctl enable --now firewalld
sudo firewall-cmd --statefirewall-cmd --state wyświetla running. Jeśli usługa jest zatrzymana, każde inne wywołanie firewall-cmd zwraca FirewallD is not running i kończy działanie z kodem błędu. Jest to pierwsza rzecz, którą należy sprawdzić, gdy polecenie wydaje się nie przynosić żadnego efektu.
Teraz należy sprawdzić, co jest aktualnie dozwolone.
sudo firewall-cmd --list-allRzeczywiste wyjście zawiera więcej linii. Istotne są następujące:
public (active)
target: default
interfaces: eth0
sources:
services: cockpit dhcpv6-client ssh
ports:
rich rules:ssh w linii services: jest powodem, dla którego bieżąca sesja nadal działa. Jeśli tego brakuje, należy dodać tę regułę przed wprowadzeniem jakichkolwiek innych zmian, ponieważ uruchomienie firewalla bez reguły SSH zakończy sesję i uniemożliwi ponowne połączenie.
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reloadtarget: default oznacza, że pakiet niepasujący do żadnej reguły jest odrzucany z odpowiedzią ICMP (internet control message protocol) typu host-prohibited, dzięki czemu klient próbujący połączyć się z zamkniętym portem natychmiast otrzymuje No route to host. Ustawienie celu na DROP sprawia, że serwer pozostaje „cichy”, a skanery oczekują na przekroczenie limitu czasu (timeout).
sudo firewall-cmd --permanent --zone=public --set-target=DROP
sudo firewall-cmd --reloadPrzed wykonaniem tego polecenia należy znać konsekwencje: DROP powoduje również, że serwer przestaje odpowiadać na ping, co sprawia, że własne systemy monitoringu również przestają otrzymywać odpowiedzi.
Dlaczego reguła zniknęła? Flaga --permanent
firewalld przechowuje jednocześnie dwie konfiguracje. Konfiguracja runtime to zestaw reguł aktualnie egzekwowany przez jądro systemu. Konfiguracja permanent to zestaw zapisany w /etc/firewalld/zones/public.xml, który jest przywracany po przeładowaniu lub restarcie serwera.
Polecenie bez flagi --permanent zmienia wyłącznie konfigurację runtime. Zmiana działa natychmiast, ale znika po przeładowaniu lub restarcie. Polecenie z flagą --permanent zapisuje plik, ale nie zmienia bieżącego stanu, więc port pozostaje zamknięty do momentu przeładowania. Żadne z tych zachowań nie jest błędem. Oba zaskakują użytkowników, ponieważ polecenie w obu przypadkach wyświetla komunikat success.
Zawsze stosuj obie opcje jednocześnie.
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reloadMożesz odczytać obie konfiguracje, co jest najszybszym sposobem na zdiagnozowanie popełnionego błędu.
sudo firewall-cmd --list-services
sudo firewall-cmd --permanent --list-servicesPierwsze polecenie wyświetla aktywny zestaw reguł. Drugie wyświetla zestaw zapisany. Jeśli aktywny zestaw zawiera usługę, której nie ma w zestawie zapisanym, reguła zniknie przy następnym przeładowaniu. Jeśli zapisany zestaw zawiera usługę, której nie ma w aktywnym, oznacza to pominięcie przeładowania. Polecenie sudo firewall-cmd --runtime-to-permanent kopiuje całą bieżącą konfigurację do pliku zapisanego, co jest przydatne po zakończeniu sesji testowej.
Polecenie --reload zachowuje stan śledzenia połączeń, dzięki czemu sesja SSH nie zostanie przerwana. Polecenie --complete-reload przeładowuje również moduły jądra i traci ten stan, co zazwyczaj kończy wszystkie otwarte połączenia, w tym bieżącą sesję. Należy używać zwykłego przeładowania.
Wbudowano jeden mechanizm bezpieczeństwa. Reguła runtime może wygasnąć automatycznie.
sudo firewall-cmd --add-service=http --timeout=5mTa reguła usuwa się sama po pięciu minutach. Nie można jej łączyć z flagą --permanent i o to właśnie chodzi: służy ona do testowania zmian, co do których nie ma pewności. Starszy mechanizm bezpieczeństwa jest skuteczniejszy. Podczas edycji reguł należy utrzymywać otwartą drugą sesję SSH i nie zamykać jej, dopóki nowe reguły nie zostaną zweryfikowane poprzez poprawne logowanie.
Strefy i dlaczego na VPS liczy się tylko strefa domyślna
Strefa to nazwany zestaw uprawnień z przypisanym poziomem zaufania. firewalld przypisuje każdy przychodzący pakiet do dokładnie jednej strefy. Najpierw dopasowuje adres źródłowy pakietu do listy sources: każdej strefy. Jeśli nie ma dopasowania, używana jest strefa przypisana do interfejsu, przez który wszedł pakiet. Jeśli interfejs nie jest przypisany do żadnej strefy, pakiet trafia do strefy domyślnej.
sudo firewall-cmd --get-default-zone
sudo firewall-cmd --get-active-zonesNa serwerze VPS z jednym interfejsem sieciowym odpowiedzią jest niemal zawsze public i jest to jedyna strefa, z której będziesz korzystać. Polecenie firewall-cmd bez argumentu --zone= działa na strefie domyślnej, dlatego każde krótkie polecenie w tym przewodniku działa bez konieczności jej wskazywania.
Oto błąd, który marnuje całe popołudnie. Jeśli interfejs jest przypisany do innej strefy, Twoje reguły trafiają do public, podczas gdy ruch jest obsługiwany gdzie indziej. W efekcie dodane reguły nie działają, a system nie wyświetla żadnego ostrzeżenia. Polecenie --get-active-zones pokazuje przypisanie:
public
interfaces: eth0Jeśli interfejs widnieje pod inną nazwą strefy, albo dodaj reguły w tej strefie za pomocą --zone=, albo przenieś interfejs.
sudo firewall-cmd --permanent --zone=public --change-interface=eth0
sudo firewall-cmd --reloadNetworkManager zarządza interfejsami w systemach Rocky i AlmaLinux i przywraca strefę przy nawiązywaniu połączenia. Ustaw ją również tam, aby restart nie cofnął wprowadzonych zmian. Pobierz nazwę połączenia z pierwszego polecenia, ponieważ rzadko jest ona taka sama jak nazwa urządzenia.
sudo nmcli connection show
sudo nmcli connection modify "System eth0" connection.zone publicDopasowanie źródła ma pierwszeństwo przed dopasowaniem interfejsu, co pozwala na zastosowanie innej polityki dla konkretnego adresu. Wbudowana strefa trusted akceptuje wszystko.
sudo firewall-cmd --permanent --zone=trusted --add-source=203.0.113.10/32
sudo firewall-cmd --reloadZachowaj ostrożność w tym przypadku. Otwiera ona wszystkie porty na serwerze dla danego adresu, w tym bazę danych, która miała być prywatna. Użyj reguły typu rich rule, jeśli chcesz otworzyć jeden port, a nie cały host.
Czym jest usługa w firewalld?
Usługa to nazwany zestaw portów dostarczany w formie pliku XML. --add-service=https otwiera 443/tcp, ponieważ /usr/lib/firewalld/services/https.xml definiuje, co oznacza https.
sudo firewall-cmd --get-services
sudo firewall-cmd --info-service=https--info-service wyświetla porty ukryte pod daną nazwą:
https
ports: 443/tcpNależy używać nazw, jeśli istnieją. Zapewnia to czytelność w --list-all po sześciu miesiącach, a pakiety takie jak Cockpit instalują własne pliki usług. Do wszystkiego, co nie posiada definicji, należy używać --add-port.
Należy uważać na różnice: usługa ssh oznacza 22/tcp i nic więcej. Jeśli SSH zostało przeniesione na inny port w ramach utwardzania dostępu SSH do serwera, to --add-service=ssh nie otworzy portu, który jest faktycznie używany.
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reloadW systemach typu RHEL na tych drzwiach znajduje się drugie zabezpieczenie. SELinux (Security-Enhanced Linux) nadaje etykiety numerom portów, a sshd nie może powiązać się z portem spoza swoich etykiet. W takim przypadku usługa odmawia startu, a w dzienniku pojawia się komunikat error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.. Należy najpierw nadać etykietę portowi.
sudo dnf install -y policycoreutils-python-utils
sudo semanage port -a -t ssh_port_t -p tcp 2222Jak sprawdzić, co jest obecnie otwarte?
sudo firewall-cmd --list-all
sudo firewall-cmd --list-rich-rules
sudo nft list table inet firewalld | head -n 40Pierwsze dwa polecenia raportują stan według firewalld. Trzecie odczytuje reguły faktycznie załadowane do jądra w tablicy należącej do firewalld. Wyniki powinny być zgodne.
Żadne z nich nie stanowi ostatecznego dowodu. Należy przeprowadzić test z innej maszyny:
nc -zv 203.0.113.20 443Nie należy uruchamiać testu na samym serwerze. firewalld akceptuje cały ruch przychodzący na interfejs loopback, więc curl http://localhost:8080 zakończy się powodzeniem niezależnie od ustawionych reguł. Taki test potwierdza jedynie, że usługa działa. Nie dostarcza żadnych informacji na temat konfiguracji firewalla.
Zezwalanie na port WWW
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-servicesOstatnie polecenie powinno teraz wyświetlać http https obok wcześniejszych wpisów. Jeśli witryna nadal nie odpowiada, problem prawdopodobnie nie leży w zaporze sieciowej. Reguła jedynie zezwala na przepływ pakietów. Proces nadal musi nasłuchiwać na danym porcie.
sudo ss -tlnpGniazdo oznaczone jako 0.0.0.0:443 lub *:443 akceptuje połączenia z dowolnego adresu. Gniazdo oznaczone jako 127.0.0.1:443 odpowiada wyłącznie na interfejsie zwrotnym (loopback) i żadna reguła zapory nie sprawi, że będzie ono dostępne z zewnątrz. Porty i gniazda nasłuchujące w systemie Linux szczegółowo omawia tę różnicę.
Jak ponownie zamknąć port?
sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --reloadZasada --permanent ma zastosowanie również w tym przypadku i jest bardziej dotkliwa w tym kierunku. Usunięcie usługi wyłącznie ze środowiska uruchomieniowego sprawia, że port wydaje się zamknięty, jednak kolejne przeładowanie lub restart systemu otworzy go ponownie na podstawie zapisanego pliku. Jest to luka, której nie zauważysz, ponieważ wykonana kontrola zakończyła się powodzeniem.
Usunięcie elementu, którego nie było, powoduje wyświetlenie komunikatu Warning: NOT_ENABLED: http i nadal kończy się kodem wyjścia 0. Dodanie tego samego elementu dwukrotnie powoduje wyświetlenie komunikatu Warning: ALREADY_ENABLED: http. Oba przypadki są bezpieczne. Błędnie wpisana nazwa to inna sytuacja: Error: INVALID_SERVICE oznacza, że firewalld nie posiada definicji o takiej nazwie i żadne zmiany nie zostały wprowadzone.
Jeśli polecenie --list-all wykazuje cockpit, a nie korzystasz z konsoli internetowej Cockpit na porcie 9090, usuń ją. Każdy otwarty port to usługa, którą należy utrzymywać w stanie aktualnym pod kątem poprawek bezpieczeństwa.
Ograniczenie portu do jednego adresu źródłowego
Reguły typu rich rules stanowią rozszerzoną formę konfiguracji, stosowaną w sytuacjach, gdy nazwa usługi nie pozwala na precyzyjne określenie wymagań. Ograniczenie dostępu do SSH dla jednego adresu biurowego wymaga wykonania dwóch poleceń, przy czym o drugim z nich często się zapomina.
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.10/32" service name="ssh" accept'
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reloadStrefa (zone) jest zbiorem uprawnień, a nie listą numerowaną, która kończy działanie na pierwszym dopasowaniu. Reguła typu rich rule dodaje akceptację dla jednego adresu. Nie blokuje ona nikogo innego. Dopóki ssh znajduje się w linii services:, cały Internet nadal ma dostęp do portu 22, a reguła typu rich rule nie zmienia niczego w mierzalny sposób. Należy usunąć ogólny wpis, w przeciwnym razie reguła szczegółowa będzie jedynie dekoracją.
W przypadku portu, który nie posiada nazwy usługi, należy wskazać bezpośrednio numer portu.
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.10/32" port port="5432" protocol="tcp" accept'Aby odrzucić ruch z uciążliwej sieci i zachować wpis w dzienniku, należy umieścić element log przed akcją, zgodnie z kolejnością wymaganą przez składnię reguł typu rich rule.
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="198.51.100.0/24" log prefix="fw-drop " level="info" limit value="3/m" drop'
sudo firewall-cmd --reload
sudo journalctl -k -g fw-dropWartość limit zapobiega zalaniu dziennika przez nadmiar pakietów. Przed zablokowaniem dostępu SSH do jednego adresu należy upewnić się, że adres ten jest stabilny. Połączenie domowe ze zmiennym adresem IP spowoduje utratę dostępu w dniu jego zmiany, dlatego należy najpierw przetestować i sprawdzić działanie dostępu do konsoli oferowanego przez dostawcę usług.
Polecenia ufw i ich odpowiedniki w firewall-cmd
Te same zadania, inne narzędzie. Każda linia --permanent wymaga dodania sudo firewall-cmd --reload, czego lista tego typu nie jest w stanie pokazać.
sudo ufw enablezmienia się wsudo systemctl enable --now firewalldsudo ufw disablezmienia się wsudo systemctl disable --now firewalldsudo ufw status verbosezmienia się wsudo firewall-cmd --list-allsudo ufw allow OpenSSHzmienia się wsudo firewall-cmd --permanent --add-service=sshsudo ufw allow 443/tcpzmienia się wsudo firewall-cmd --permanent --add-port=443/tcpsudo ufw delete allow 443/tcpzmienia się wsudo firewall-cmd --permanent --remove-port=443/tcpsudo ufw allow from 203.0.113.10 to any port 22zmienia się w powyższą regułę typu rich rulesudo ufw reloadzmienia się wsudo firewall-cmd --reloadsudo ufw default deny incomingto domyślne zachowanie strefypublic, a--set-target=DROPjest jej cichą wersjąsudo ufw logging onzmienia się wsudo firewall-cmd --set-log-denied=all
Jedną różnicę należy podkreślić wyraźnie. ufw utrzymuje numerowaną listę, co pozwala na wstawienie reguły na pozycji 1. firewalld nie używa numerów reguł, więc polecenie „umieść tę regułę na początku” nie ma tutaj zastosowania. Gdy dwa wpisy w firewalld wydają się sprzeczne, wygrywa reguła zezwalająca (accept), ponieważ w zbiorze nie ma domyślnych reguł odrzucających. Szerokie reguły należy usuwać ręcznie.
Dlaczego kontener Docker jest dostępny, mimo że firewall wydaje się zamknięty?
Opublikowany port kontenera nigdy nie dociera do części firewalla kontrolowanej przez strefę. docker run -d -p 8080:80 nginx nakazuje programowi Docker utworzenie własnych reguł NAT (network address translation) oraz przekierowań. Pakiet docierający na port 8080 jest przepisywany i kierowany bezpośrednio do kontenera, więc jest przekazywany (forwarded), a nie dostarczany do hosta. Linie services: oraz ports: w strefie zarządzają pakietami dostarczanymi do hosta. Reguły Dockera zarządzają ścieżką przekazywania i akceptują ruch.
Efektem jest serwer, na którym sudo firewall-cmd --list-all nie wykazuje portu 8080, a nc -zv 203.0.113.20 8080 z innej maszyny mimo to nawiązuje połączenie. Należy sprawdzić, co zainstalował Docker:
sudo iptables -t nat -L DOCKER -nRozwiązanie polega na zmianie flagi publikowania. Powiąż port z interfejsem loopback i umieść przed nim reverse proxy.
docker run -d -p 127.0.0.1:8080:80 nginxKontener odpowiada teraz na curl http://127.0.0.1:8080 lokalnie na serwerze i nie przyjmuje połączeń z zewnątrz. Użytkownicy Ubuntu napotykają ten sam problem, opisany w dlaczego kontenery Docker publikują porty z pominięciem ufw. Podman działający z uprawnieniami root, dostępny w podstawowych repozytoriach systemów Rocky i AlmaLinux, publikuje porty przy użyciu tego samego mechanizmu NAT, dlatego należy przeprowadzić test z innej maszyny, zamiast polegać wyłącznie na liście strefy.
Zapewnienie trwałości po restarcie i typowe błędy
sudo systemctl is-enabled firewalld
sudo systemctl status firewalldenabled oraz active (running) to polecenia, których należy użyć. Firewall, który działa, ale nie jest włączony do autostartu, chroni serwer tylko do pierwszego restartu. Weryfikacja tego stanu powinna znaleźć się na liście zadań w pierwsze dziesięć minut na nowym VPS, obok kluczy SSH i aktualizacji.
Bezpośrednie polecenia nftables i firewalld nie współpracują ze sobą. firewalld zarządza tablicą o nazwie inet firewalld. sudo nft flush ruleset usuwa tę tablicę, co otwiera serwer na cały ruch, podczas gdy firewall-cmd --list-all nadal wyświetla zamierzoną konfigurację, ponieważ firewalld raportuje swój stan wewnętrzny, a nie faktyczny stan jądra. sudo firewall-cmd --reload przywraca reguły. Reguły należy zapisywać za pomocą firewall-cmd, aby były aktywne po przeładowaniu.
Dwa systemy zarządzania firewallem na jednym serwerze. Instalacja ufw lub iptables-services obok firewalld powoduje, że dwa programy modyfikują reguły bez wzajemnej wiedzy, a ostateczny stan zależy od tego, która usługa uruchomiła się jako ostatnia. Należy wybrać jedno rozwiązanie. W systemach Rocky i AlmaLinux wspieranym rozwiązaniem jest firewalld.
Firewall dostawcy przed serwerem. Wiele paneli VPS posiada zewnętrzny firewall sieciowy. Jeśli --list-all wskazuje, że port jest otwarty, a połączenie z zewnątrz nadal nie działa, należy sprawdzić panel przed wprowadzeniem zmian na serwerze. Działa to również w drugą stronę: otwarta reguła w panelu nie przyniesie efektu, jeśli firewalld odrzuca pakiet.
Uruchamianie firewall-cmd bez sudo. Każda zmiana wymaga uprawnień root. W przeciwnym razie żądanie jest odrzucane przez mechanizm autoryzacji i nic nie zostaje zmodyfikowane, co na pierwszy rzut oka może wyglądać tak, jakby polecenie zostało zignorowane.
Sześć poleceń wystarcza do codziennej pracy: --list-all do odczytu stanu, --permanent --add-service lub --add-port do otwarcia portu, --permanent --remove-service do jego zamknięcia, --reload do wczytania zapisanego pliku oraz --runtime-to-permanent po serii testów. Strefa to public, flaga to --permanent, a jedynym wiarygodnym testem jest sprawdzenie połączenia z innej maszyny.
FAQ
Dlaczego moja reguła firewalld zniknęła po restarcie?
Reguła została dodana tylko do konfiguracji uruchomieniowej. sudo firewall-cmd --add-service=http działa natychmiast, ale jest usuwana przy kolejnym przeładowaniu lub restarcie, ponieważ zapisana konfiguracja w /etc/firewalld/zones/public.xml nie została zmodyfikowana. Dodaj --permanent, a następnie wykonaj sudo firewall-cmd --reload. Aby zachować reguły dodane ręcznie, wykonaj sudo firewall-cmd --runtime-to-permanent, co skopiuje bieżący zestaw reguł do pliku zapisanego.
Dlaczego po dodaniu reguły z flagą --permanent nic się nie zmienia?
Ponieważ --permanent zapisuje plik, ale nie ingeruje w działający firewall. Port pozostaje zamknięty, dopóki sudo firewall-cmd --reload nie załaduje zapisanej konfiguracji do jądra systemu. Porównaj sudo firewall-cmd --list-services z sudo firewall-cmd --permanent --list-services: jeśli zapisana lista zawiera wpis, którego nie ma na liście aktywnej, oznacza to, że brakuje przeładowania.
Czy powinienem użyć --add-service czy --add-port?
Użyj --add-service, gdy istnieje nazwa dla uruchamianej usługi. Określa ona intencję, a sudo firewall-cmd --info-service=https pokazuje dokładnie, które porty obejmuje dana nazwa. Użyj --add-port, gdy usługa nie jest zdefiniowana lub nasłuchuje na niestandardowym porcie. Usługa ssh oznacza tylko port 22/tcp, więc SSH przeniesione na 2222 wymaga --add-port=2222/tcp oraz etykiety SELinux dla tego portu.
Dlaczego mój kontener Docker jest dostępny, mimo że firewall-cmd pokazuje, iż port jest zamknięty?
Opublikowany port jest nadpisywany przez własne reguły NAT Dockera i przekazywany do kontenera, więc pakiet nigdy nie trafia do hosta, a listy usług i portów w strefie dotyczą tylko pakietów dostarczanych do hosta. Kontener odpowiada na zapytania z Internetu, podczas gdy --list-all nic nie wykazuje. Publikuj porty na interfejsie loopback za pomocą docker run -d -p 127.0.0.1:8080:80 nginx i umieść przed nimi reverse proxy.
Czy mogę zainstalować ufw na Rocky Linux zamiast firewalld?
Dwa menedżery zapory sieciowej na jednym serwerze tworzą reguły bez wzajemnej wiedzy o sobie, a to, który zestaw przetrwa, zależy od tego, która usługa wystartowała jako ostatnia. firewalld jest wspieranym narzędziem w systemach Rocky Linux i AlmaLinux, jest zainstalowany domyślnie i zarządza tym samym backendem nftables, którego używałby ufw. Poznaj domyślną strefę oraz flagę --permanent, a opanujesz całe narzędzie.