Najkrótsza odpowiedź: nie wczytujemy gotowego rulesetu na zdalnym serwerze „na próbę”. Najpierw ustalamy, kto obecnie zarządza regułami, zapisujemy stan, przygotowujemy drogę powrotu i zostawiamy otwartą pierwszą sesję SSH. Dopiero nowa sesja SSH oraz test usług potwierdzają, że zmiana jest poprawna.
W tym artykule odpowiadamy kolejno na praktyczne pytania: czy na danym hoście potrzebna jest migracja, co trzeba sprawdzić, jak wybrać model odpowiedzialności za firewall, jak zbudować i przetestować politykę, a następnie jak zachować ją po restarcie. Przykładowy ruleset dotyczy pojedynczego serwera WWW; nie jest konfiguracją dla routera ani bezrefleksyjnym fragmentem do wklejenia na produkcję.
Spis treści
Czy ten artykuł dotyczy mojego serwera?
Tak, jeśli administrujesz Debianem 13 i chcesz świadomie uporządkować firewall oparty dotąd na iptables. Nie zawsze oznacza to jednak wymianę mechanizmu działającego w jądrze. W typowej instalacji Debiana polecenie iptables może być już wariantem iptables-nft: przyjmuje dawną składnię, ale zapisuje reguły w podsystemie nf_tables, czyli tym samym, którym zarządza nft. Migracja polega wtedy głównie na przejęciu odpowiedzialności za opis i trwałość reguł, a nie na „włączeniu nftables”.
Artykuł jest przeznaczony dla hosta, na którym znasz usługi nasłuchujące oraz źródła administracyjne. Nie rozpoczynaj migracji podczas incydentu, z jedynej sesji SSH ani wtedy, gdy nie wiesz, czy reguły tworzą Docker, UFW, firewalld, fail2ban albo mechanizm dostawcy chmury. Najpierw zbierz fakty.
- Nie migruj od razu, jeżeli obecny ruleset działa, a nie masz okna testowego lub dostępu przez konsolę dostawcy. Samo
iptables-nftnie jest błędem wymagającym pilnej naprawy. - Przejdź na natywne nftables, gdy chcesz trzymać czytelny ruleset w repozytorium, używać jednej tabeli
inetdla IPv4 i IPv6 albo zastąpić wiele podobnych reguł zbiorem adresów. - Wybierz osobny projekt, jeżeli host jest routerem, ma Kubernetes, złożony NAT, kilka interfejsów lub reguły kontenerów. Ten tekst pokazuje politykę wejściową pojedynczego serwera, nie gotową konfigurację routingu.
Jakie pojęcia trzeba znać przed zmianą?
Najpierw nazwy. Dzięki temu polecenia i plik konfiguracyjny nie będą wyglądały jak niepowiązane zaklęcia.
- Ruleset to cały aktywny zestaw reguł firewalla w jądrze: wszystkie tabele, łańcuchy, zbiory i liczniki.
- Tabela jest kontenerem na reguły. Własna tabela, na przykład
inet site_filter, pozwala oddzielić politykę administratora od tabel tworzonych przez inne usługi. - Łańcuch bazowy jest miejscem, w którym pakiet trafia do reguł. Dla połączenia kierowanego do hosta używamy
hook input; ruch przechodzący przez router trafia dohook forward; pakiety wysyłane przez sam host dohook output. - Polityka
dropoznacza, że pakiet, który nie pasuje do żadnej reguły dopuszczającej, zostaje odrzucony na końcu łańcucha. To nie jest „domyślna ochrona całego systemu”, lecz decyzja konkretnego łańcucha bazowego. - Conntrack to pamięć jądra o połączeniach. Reguła
ct state established,related acceptwpuszcza odpowiedzi na połączenia już rozpoczęte przez klienta lub hosta, na przykład odpowiedź serwera APT albo kolejne pakiety działającej sesji SSH. - Rodzina
inetpozwala użyć jednego łańcucha dla IPv4 i IPv6. Regułatcp dport 443 acceptobejmie oba protokoły; ograniczenie źródła IPv4 wymaga już jawnegoip saddr, a IPv6 -ip6 saddr.
W nftables accept kończy ocenę bieżącego łańcucha, ale pakiet może jeszcze trafić do innego łańcucha bazowego podpiętego do tego samego etapu. Dlatego reguły Dockera lub fail2ban nadal mogą go odrzucić. Werdykt drop jest ostateczny: odrzucony pakiet nie będzie już „uratowany” późniejszą regułą.
Co sprawdzić i zapisać przed migracją?
Poniższe polecenia wykonujemy jako root na hoście. Są wyłącznie odczytem aktualnego stanu; niczego nie zmieniają.
iptables --version
update-alternatives --display iptables
iptables -S
ip6tables -S
iptables-legacy -S
ip6tables-legacy -S
nft list ruleset
nft list tables
systemctl is-enabled nftables netfilter-persistent ufw firewalld docker fail2ban 2>&1
systemctl is-active nftables netfilter-persistent ufw firewalld docker fail2ban 2>&1
ss -lntup
Wynik iptables ... (nf_tables) wskazuje warstwę zgodności z nftables. Wynik (legacy) oznacza osobny, starszy zestaw reguł; sprawdzamy go osobno, ponieważ nft list ruleset go nie pokaże. Lista usług odpowiada na inne pytanie: kto może dodać regułę dziś albo po restarcie. Z kolei ss -lntup pozwala spisać faktycznie otwarte porty, zanim zaczniemy opisywać politykę.
Zapisz stan w katalogu dostępnym tylko dla roota. Zrzut nie jest jeszcze planem migracji, ale daje materiał do porównania i awaryjnego powrotu.
install -d -m 0700 /root/firewall-backup
iptables-save > /root/firewall-backup/iptables.v4.before
ip6tables-save > /root/firewall-backup/iptables.v6.before
nft list ruleset > /root/firewall-backup/ruleset.before.nft
test -e /etc/nftables.conf && \
cp -a /etc/nftables.conf /root/firewall-backup/nftables.conf.before
Jeżeli korzystasz z firewalla dostawcy chmury, security group lub zapory przed hostem, spisz go również. Taka warstwa nie jest widoczna w nft i może sprawić, że zewnętrzny test wygląda dobrze albo źle z innego powodu niż lokalny ruleset.
Dlaczego potrzebne są dwie sesje SSH?
Zostaw terminal A z obecną sesją jako drogę powrotu. Terminal B otwórz po wczytaniu nowej polityki i użyj do faktycznego testu. Stara sesja zwykle nadal działa dzięki ct state established; jej przetrwanie nie dowodzi, że nowy klient będzie mógł się zalogować.
# Uruchom na drugim komputerze lub w drugim terminalu.
# Zastąp dane przykładowe prawdziwym portem, użytkownikiem i adresem hosta.
ssh -o ConnectTimeout=5 -p 22 admin@server.example
Nie zamykaj terminala A ani dostępu przez konsolę dostawcy, dopóki nie wykonasz testu z terminala B i testu usług z właściwej sieci źródłowej.
Jaki wariant migracji wybrać?
Najpierw zdecyduj, kto ma być właścicielem reguł. Nie mieszaj modeli tylko dlatego, że każde narzędzie używa dziś nftables w jądrze.
| Wariant | Kiedy ma sens | Najważniejsza zasada |
|---|---|---|
Pozostawienie iptables-nft | Nie masz czasu na pełną inwentaryzację albo oprogramowanie nadal zarządza regułami przez iptables. | Nie zmieniaj alternatyw ani trwałości „dla porządku”. Najpierw zaplanuj migrację. |
| Własna tabela nftables | Chcesz zarządzać polityką hosta, ale Docker, fail2ban lub inna usługa ma własne tabele. | Usuwaj i odtwarzaj wyłącznie swoją nazwaną tabelę; nie kasuj całego rulesetu. |
| Pełny ruleset nftables | Jedna konfiguracja ma świadomie zarządzać wszystkimi regułami hosta. | flush ruleset jest dopuszczalne wyłącznie wtedy, gdy każda usunięta tabela i stan dynamiczny są pod Twoją kontrolą. |
Wariant z własną tabelą nie jest sposobem na ukrycie starej polityki. Nowy łańcuch z policy drop będzie filtrował ruch niezależnie od tego, czy stare reguły go akceptują. Przed wczytaniem trzeba więc opisać wszystkie potrzebne usługi, a stare reguły wycofać w świadomie zaplanowanym etapie.
Czy iptables-translate zrobi migrację za mnie?
Nie. Narzędzia tłumaczą składnię, nie podejmują decyzji o usłudze, źródle ani kolejności wdrożenia. Są jednak bardzo przydatne jako lista tego, co trzeba ręcznie przejrzeć.
iptables-translate -A INPUT -p tcp --dport 22 -j ACCEPT
iptables-restore-translate -f /root/firewall-backup/iptables.v4.before
Pierwsze polecenie nie zmienia systemu i pokazuje odpowiednik jednej reguły. Drugie tłumaczy zrzut IPv4. Wynik zachowaj jako materiał roboczy: sprawdź ręcznie moduły, których nie przełożył, polityki łańcuchów, IPv6 oraz reguły specyficzne dla Dockera lub fail2ban. Dopiero potem twórz docelową konfigurację.
Jak zbudować czytelny ruleset dla serwera?
Zanim napiszesz pierwszą regułę, odpowiedz na pięć konkretnych pytań:
- Na jakim porcie i z jakich adresów źródłowych administrator ma łączyć się przez SSH?
- Które usługi są publiczne, a które powinny być widoczne wyłącznie z sieci administracyjnej lub monitoringu?
- Czy host ma obsługiwać IPv6? Jeżeli tak, które źródła IPv6 i komunikaty ICMPv6 są niezbędne?
- Czy host jest tylko serwerem, czy także przekazuje ruch do kontenerów, maszyn wirtualnych lub innych sieci?
- Która usługa ładuje politykę po restarcie?
Odpowiedzi są ważniejsze niż forma składni. Poniższy przykład dotyczy tylko ruchu input do jednego serwera WWW. Celowo nie zawiera łańcucha forward; bez osobnego projektu nie wolno kopiować polityki drop na host z Dockerem, routowaniem lub mostami sieciowymi.
Dlaczego reguła ct state jest na początku?
ct state established,related accept wpuszcza pakiety należące do połączeń, które host już zaakceptował albo sam rozpoczął. Dzięki niej odpowiedź na pobranie aktualizacji, połączenie zwrotne FTP lub kolejne pakiety aktywnej sesji SSH nie muszą pasować do osobnej reguły portu. Nie wpuszcza natomiast nowego połączenia administracyjnego - za to odpowiada reguła z portem i, najlepiej, ze źródłem.
Dlaczego adresy administratorów zapisujemy w zbiorze?
Zbiór (set) to nazwana lista adresów lub podsieci. Zamiast tworzyć jedną regułę SSH na każdy adres, definiujemy listę raz, a reguła odwołuje się do jej nazwy. Flaga interval pozwala umieścić w niej także podsieć.
set ssh_admin_v4 {
type ipv4_addr
flags interval
elements = { 198.51.100.0/24 }
}
ip saddr @ssh_admin_v4 tcp dport 22 accept
Adres 198.51.100.0/24 należy do sieci dokumentacyjnej i nie jest adresem, którego można zostawić na produkcji. Przed testem zastąp go prawdziwym, zatwierdzonym źródłem administracyjnym. Jeżeli SSH ma być dostępne również z IPv6, użyj osobnego zbioru typu ipv6_addr oraz jawnej reguły ip6 saddr.
Jak wygląda minimalna polityka wejściowa?
Poniższy plik jest wzorcem własnej tabeli. Nie używa flush ruleset, więc podczas jego wczytania nie kasuje tabel Dockera ani fail2ban. Wstaw go najpierw do pliku testowego, na przykład /root/site_filter.nft, i nie wczytuj bez zastąpienia portu SSH oraz sieci administracyjnej.
#!/usr/sbin/nft -f
# Ta linia usuwa wyłącznie poprzednią wersję własnej tabeli.
destroy table inet site_filter
table inet site_filter {
set ssh_admin_v4 {
type ipv4_addr
flags interval
# Sieć dokumentacyjna - zastąp ją przed wdrożeniem.
elements = { 198.51.100.0/24 }
}
chain input {
type filter hook input priority filter; policy drop;
ct state established,related accept
ct state invalid drop
iifname "lo" accept
# Dopasuj zestaw ICMPv6 do roli hosta i używanej sieci.
icmp type echo-request limit rate 10/second accept
icmpv6 type { destination-unreachable, packet-too-big, time-exceeded,
parameter-problem, echo-request, nd-router-solicit,
nd-router-advert, nd-neighbor-solicit,
nd-neighbor-advert } accept
ip saddr @ssh_admin_v4 tcp dport 22 accept
tcp dport { 80, 443 } accept
limit rate 5/second log prefix "site_filter input drop: " level info
counter
}
}
Reguła tcp dport { 80, 443 } accept otwiera HTTP i HTTPS przez IPv4 oraz IPv6, bo tabela ma rodzinę inet. SSH w przykładzie jest dopuszczone wyłącznie z IPv4 zapisanych w zbiorze. Ostatnie dwie linie logują z ograniczeniem tempa i zliczają pakiety, a następnie pakiet trafia na policy drop. Licznik counter jest opcjonalny; dodaj go tylko tam, gdzie statystyka będzie używana.
Jak przetestować ruleset bez utraty dostępu SSH?
Najpierw sprawdź składnię. Opcja -c nie stosuje zmian w jądrze, lecz sprawdza poprawność pliku i odwołań w rulesecie.
nft -c -f /root/site_filter.nft
Jeżeli kontrola przejdzie, a terminal A i konsola awaryjna nadal są dostępne, możesz wczytać testową tabelę. Plik z destroy table inet site_filter i nową deklaracją tabeli jest wykonywany jako jeden wsad; zmienia tylko tę tabelę.
nft -f /root/site_filter.nft
nft -a list table inet site_filter
Natychmiast przejdź do terminala B i otwórz nową sesję SSH. Potem, z zewnętrznego hosta należącego do właściwej sieci, sprawdź usługę WWW oraz każdy port ograniczony do źródła. Przykładowe wartości trzeba zastąpić danymi danego hosta.
ssh -o ConnectTimeout=5 -p 22 admin@server.example
curl --fail --silent --show-error --head https://server.example/
Gdy test własnej tabeli się nie powiedzie, nie zamykaj terminala A. Jeżeli tabela site_filter została utworzona po raz pierwszy, cofnięcie jej jest wąskie i nie dotyka tabel innych usług:
nft destroy table inet site_filter
Jeżeli tabela istniała przed zmianą, zapisz jej poprzednią wersję przed wczytaniem i odtwórz ją przez nft -f; nie kasuj w ciemno tabeli, której poprzedniej zawartości nie znasz.
Jak zabezpieczyć pełną migrację na hoście bez konsoli?
Ten wariant dotyczy wyłącznie hosta, którego cały ruleset jest własnością jednej konfiguracji działającej w nf_tables. Nie stosuj tego timera jako drogi powrotu z iptables-legacy: legacy to osobny silnik i snapshot nft list ruleset go nie odtworzy. Przy aktywnym legacy potrzebujesz konsoli awaryjnej albo osobnego, przetestowanego planu powrotu.
Na hoście z pełną polityką nftables utwórz snapshot w formacie, który nft -f potrafi odtworzyć atomowo:
{ printf 'flush ruleset\n'; nft list ruleset; } \
> /root/firewall-backup/ruleset.before.nft
Możesz następnie uruchomić jednorazowy timer powrotu. Robimy to tylko wtedy, gdy rozumiemy, że snapshot przywróci cały stan nftables z chwili zapisu; na hoście z dynamicznymi tabelami Dockera lub fail2ban taki powrót może cofnąć również ich bieżący stan.
rm -f /run/nft-change-confirmed
setsid sh -c 'sleep 180; test -e /run/nft-change-confirmed || nft -f /root/firewall-backup/ruleset.before.nft' \
</dev/null >/dev/null 2>&1 &
nft -f /etc/nftables.conf
Po udanym teście z terminala B potwierdź zmianę; nie kasuj od razu backupu.
touch /run/nft-change-confirmed
Jeżeli nowa sesja nie przejdzie, poczekaj na timer albo użyj konsoli awaryjnej do odtworzenia snapshotu. Nie próbuj „naprawiać” problemu przez systemctl stop nftables ani przez ręczne nft flush ruleset.
Kiedy nie używać flush ruleset?
nft flush ruleset kasuje wszystkie tabele we wszystkich rodzinach i pozostawia pusty ruleset. Nie jest odpowiednikiem bezpiecznego wyłączenia pojedynczej polityki ani poleceniem diagnostycznym. W standardowej jednostce nftables Debiana polecenie zatrzymania usługi wykonuje właśnie taki globalny flush, dlatego do zastosowania zmienionego pliku używamy systemctl reload nftables, a nie restart ani stop.
Globalny flush ruleset ma sens tylko wtedy, gdy spełnione są wszystkie warunki: jedna konfiguracja jest właścicielem całego rulesetu, znasz wszystkie usługi zależne od reguł, masz przetestowany plik pełnej polityki i drogę powrotu. Nie używaj go na hoście, na którym trzeba zachować reguły lub stan tworzony przez inne komponenty.
| Komponent | Co może znajdować się w rulesecie | Bezpieczna decyzja |
|---|---|---|
| Docker | Reguły NAT i filtrowania dla sieci oraz opublikowanych portów kontenerów. | Nie edytuj tabel Dockera ręcznie i nie dodawaj polityki drop do forward bez osobnego testu przepływu kontenerów. |
| fail2ban | Dynamiczne zbiory adresów z banami, często w osobnej tabeli nftables. | Globalny flush usunie aktywne bany. Zachowaj jego tabelę albo zaplanuj odtworzenie i test mechanizmu banów. |
| UFW lub firewalld | Reguły tworzone przez nakładkę, a nie przez ręcznie utrzymywany plik. | Wybierz jeden właścicielski model: nakładkę albo własne nftables. Nie utrzymuj równolegle dwóch niezależnych polityk. |
| iptables-persistent | Reguły iptables ładowane po restarcie przez netfilter-persistent. | Zostaw go do czasu pozytywnego testu; przed finalnym rebootem wyłącz jego automatyczny start, aby stara polityka nie wróciła. |
Na Dockerze sprawdź dokumentację używanej wersji i własną konfigurację demona: Docker może stosować backend iptables albo nftables, a struktura jego tabel nie jest publicznym API do ręcznej edycji. Na serwerze z aktywnym UFW lub firewalld zatrzymaj się na decyzji architektonicznej - nie wczytuj równolegle przykładowego /etc/nftables.conf.
Jak zachować politykę po restarcie i jak ją zweryfikować?
Po udanym teście przenieś zatwierdzony plik do docelowego procesu wdrożeniowego: repozytorium, Ansible lub kontrolowanego edytora. Dopiero gdy wybrałeś natywne nftables jako właściciela polityki i plik znajduje się w /etc/nftables.conf, włącz ładowanie go przy starcie.
nft -c -f /etc/nftables.conf
systemctl enable nftables.service
systemctl reload nftables.service
# Wykonaj tylko po pozytywnym teście i tylko gdy przejmujesz trwałość od iptables-persistent.
systemctl disable netfilter-persistent.service
reload wczytuje plik bez etapu ExecStop. Nie usuwaj jeszcze pakietów iptables ani iptables-persistent: zachowaj je oraz snapshoty do czasu kontrolowanego restartu. Usunięcie pakietu jest porządkiem po migracji, a nie warunkiem jej działania; niektóre zależności nadal używają poleceń iptables w wariancie zgodności.
Restart planujemy w oknie serwisowym, z konsolą awaryjną i testem z niezależnego hosta. Po starcie sprawdzamy zarówno usługę, jak i rzeczywiste reguły oraz dostępność usług:
systemctl is-active nftables.service
systemctl is-enabled nftables.service
journalctl -u nftables.service -b --no-pager
nft list ruleset
ss -lntup
Na końcu ponownie otwórz nową sesję SSH z zatwierdzonego źródła i wykonaj test HTTP, HTTPS, monitoringu lub innych usług, które wpisałeś do polityki. Dopiero po takim teście można usunąć poprzedni mechanizm trwałości i wykonać porządki w starych plikach.
Checklista: czy migracja jest gotowa?
- Sprawdziłem wariant
iptables, osobny staniptables-legacyoraz pełnynft list ruleset. - Zapisałem zrzuty IPv4, IPv6 i nftables w katalogu dostępnym tylko dla roota.
- Wiem, kto ładuje reguły dziś i kto ma je ładować po restarcie.
- Spisałem port SSH, źródła administracyjne, usługi publiczne, usługi ograniczone i decyzję dotyczącą IPv6.
- Wybrałem świadomie własną tabelę albo pełny ruleset; nie zastosowałem globalnego
flush rulesetna hoście z cudzymi tabelami. - Sprawdziłem plik przez
nft -c -fprzed zastosowaniem. - Zostawiłem działającą sesję SSH, konsolę awaryjną lub zaplanowany powrót oraz przetestowałem nową sesję SSH.
- Sprawdziłem usługę z zewnątrz, a na hoście z Dockerem lub fail2ban także ich faktyczne działanie.
- Włączyłem
nftables.servicei wyłączyłem stary loader dopiero po pozytywnym teście. - Zweryfikowałem ruleset i usługi po kontrolowanym restarcie, zanim usunąłem backupy lub stare pakiety.
Źródła i dalsza dokumentacja
- Debian: nft(8) - składnia, transakcje, tabele i łańcuchy.
- Debian 13: jednostka nftables.service - różnica między
reloadastop/restart. - Projekt nftables: przejście z iptables - mapowanie pojęć i poleceń.
- Docker: firewall z nftables - zasady współistnienia i ograniczenia backendu.
Migracja firewalla na produkcyjnym serwerze?
Porządkujemy reguły, dostępy źródłowe i trwałość firewalla, a każdą zmianę weryfikujemy z nowej sesji SSH oraz testem usług.
Powiązany artykuł
Zaawansowany Nginx na Debianie 13
Druga warstwa ograniczania ruchu: limit_req i limit_conn w aplikacji WWW.
Zobacz też