Konfiguracja firewalla UFW bez odcinania sobie dostępu

Opublikowano 15 min czytania

Właściwa kolejność przy budowaniu UFW, reguły IPv6, nftables jako backend, ograniczanie tempa przez ufw limit oraz droga powrotna przez konsolę, jeśli mimo wszystko coś pójdzie nie tak.

Filtr pakietów na serwerze root to nie ozdoba dla ambitnych, tylko wyposażenie podstawowe. UFW (Uncomplicated Firewall) załatwia to przyjemnie prosto, ma jednak cechę, która co roku odcina tysiące administratorów od ich własnych serwerów: polecenie uzbrajające firewalla jest dokładnie tym samym, które potrafi zerwać trwającą sesję SSH. Ten poradnik pokazuje kolejność, przy której to się nie zdarza, oraz, co prawie ważniejsze, drogę powrotną na wypadek, gdyby jednak się zdarzyło.

Wszystkie informacje dotyczą Debiana 13 (trixie), Debiana 12 (bookworm), Ubuntu 24.04 LTS i Ubuntu 22.04 LTS. Polecenia są napisane pod pracę na koncie root. Jeśli pracujesz jako zwykły użytkownik, poprzedź każde polecenie słowem sudo.

Dlaczego o wszystkim decyduje kolejność

Klasyczny błąd wygląda tak: ktoś najpierw ustawia politykę domyślną na „odrzucaj cały ruch przychodzący”, włącza firewalla, a dopiero potem chce spokojnie dopisać regułę dla SSH. Dokładnie pomiędzy tymi krokami leży okno czasowe, w którym serwer przestaje być osiągalny.

Powód, dla którego ten błąd tak często pozostaje niezauważony, jest bardziej podstępny niż sam błąd. UFW przynosi w pliku /etc/ufw/before.rules regułę, która przepuszcza już istniejące połączenia:

-A ufw-before-input -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

Twoja bieżąca sesja SSH jest istniejącym połączeniem. Przeżywa więc włączenie firewalla nawet wtedy, gdy żadna reguła dla SSH w ogóle nie istnieje. Prompt zostaje na miejscu, wszystko sprawia wrażenie poprawnego. Dopiero kolejna próba połączenia, czyli zwykle twoje logowanie następnego ranka, kończy się timeoutem. Dlatego obowiązuje zasada: dopóki firewall nie zostanie zweryfikowany drugą, świeżo nawiązaną sesją, nie wychodź z pierwszej sesji.

Zasada praktyczna: najpierw zezwól, potem odrzucaj, potem włącz, potem sprawdź drugą sesją, i dopiero wtedy zamknij pierwszą sesję.

Przed pierwszym poleceniem: droga ratunkowa i inwentaryzacja

Zanim zmienisz cokolwiek w filtrowaniu pakietów, wyjaśnij dwie rzeczy.

1. Jak dostaniesz się na serwer bez SSH?

Przy serwerach root KVM i serwerach dedykowanych od KernelHost konsolę VNC otwierasz wprost w panelu klienta. Ta konsola nie wisi na stosie sieciowym systemu gościa, tylko na warstwie wirtualizacji względnie na samym przyłączu sieciowym. Reguła firewalla wewnątrz systemu gościa nie może jej więc zablokować. Zaloguj się przez tę konsolę raz wcześniej i upewnij się, że znasz hasło roota. Droga ratunkowa, którą wypróbowuje się po raz pierwszy dopiero w sytuacji awaryjnej, nie jest żadną drogą ratunkową.

2. Co w ogóle nasłuchuje na tym serwerze?

Reguły dla usług, których nie ma, są nieszkodliwe. Usługa, o której zapomniałeś, kosztuje cię dostęp albo przestój. Zrób sobie przegląd:

ss -lntup

Kolumna Local Address:Port czysto rozróżnia przy tym 0.0.0.0:22 (tylko IPv4), [::]:22 (IPv6, a przez gniazdo dual stack zwykle również IPv4) oraz 127.0.0.1:3306 (tylko lokalnie, nie potrzebuje reguły firewalla). Wszystko, co jest podpięte pod 127.0.0.1 albo ::1, nie wymaga otwierania.

Szczególnie ważny jest rzeczywisty port SSH. Nie zgaduj, sprawdź. Polecenie potrzebuje prawa odczytu kluczy hosta, działa więc jako root względnie z sudo:

sudo sshd -T | grep -i "^port "

Szczegół, który wiele poradników przemilcza: na Ubuntu 24.04 usługa SSH startuje przez aktywację socketem, czyli przez ssh.socket, a nie przez ssh.service. Polecenie systemctl is-enabled ssh.socket zwraca tam enabled, a dla ssh.service zwraca disabled. Na Debianie 12, Debianie 13 i Ubuntu 22.04 jest dokładnie odwrotnie, tam obowiązuje klasyczna usługa działająca stale.

Konsekwencja jest w tym temacie nieprzyjemnie konkretna: na Ubuntu 24.04 port, który zgłasza sshd -T, nie musi być portem, na którym faktycznie odbywa się nasłuch. Miarodajny jest tam ListenStream/lib/systemd/system/ssh.socket względnie w pliku uzupełniającym w katalogu /etc/systemd/system/ssh.socket.d/. Kto zmienił swój port SSH i zdaje się na sshd -T, otwiera w UFW zły numer portu i odcina sobie dostęp przy kolejnym logowaniu. Na wszystkich czterech systemach pewne jest wyłącznie spojrzenie na proces, który naprawdę nasłuchuje:

sudo ss -lntp | grep sshd

3. Wyłącznik awaryjny

Na wypadek, gdyby coś poszło nie tak, załóż sobie przed ryzykowną zmianą wyłącznik czasowy, który po dziesięciu minutach sam z siebie wyłączy firewalla:

nohup sh -c 'sleep 600; ufw disable' >/dev/null 2>&1 &

Jeśli wszystko zadziałało, przerwij go:

pkill -f 'sleep 600; ufw disable'

Polecenie pkill trafia wyłącznie w otaczający proces shella. Sam sleep działa dalej jako sierota i kończy się bez konsekwencji, bo nie ma już nikogo, kto mógłby po nim wywołać ufw disable.

Kolejność, która nie odcina dostępu

Na Debianie UFW z reguły nie jest preinstalowany, na Ubuntu Server zazwyczaj już tak. Instalacja w żadnym wypadku nie zaszkodzi:

apt-get update
apt-get install -y ufw
ufw version

Teraz kolejność, i to dokładnie taka:

ufw allow 22/tcp comment 'SSH'
ufw default deny incoming
ufw default allow outgoing
ufw --force enable

Cztery uwagi do tego:

  • Reguła zezwalająca stoi przed wszystkim innym. UFW przyjmuje reguły również w stanie nieaktywnym i zapisuje je w /etc/ufw/user.rules. Przy włączeniu są od razu na miejscu.
  • Zamiast 22/tcp możesz użyć profilu aplikacji, na przykład ufw allow OpenSSH. Nie zdawaj się jednak na to w ciemno: profile nie pochodzą od samego UFW, tylko z zainstalowanych pakietów. Na Ubuntu katalog /etc/ufw/applications.d/ bez zainstalowanych usług jest pusty, a ufw app list wypisuje tam jedynie nagłówek Available applications: i ani jednej pozycji. Na Debianie już sam pakiet ufw przynosi około 38 profili, a profil SSH nazywa się tam SSH. Profil OpenSSH pochodzi na obu dystrybucjach z pakietu openssh-server, na serwerach jest to więc przypadek typowy. Przy odbiegającym porcie SSH profil i tak trafia w próżnię. Które profile zna twój system, pokazuje ufw app list; zapis oparty na porcie, czyli ufw allow 22/tcp, działa natomiast identycznie na wszystkich czterech systemach i dlatego jest wyborem pewniejszym.
  • ufw enable pyta interaktywnie: Command may disrupt existing ssh connections. Proceed with operation (y|n)?. W skryptach i w rolach Ansible bierz ufw --force enable, inaczej przebieg zawiśnie.
  • Komentarz podany po comment pojawia się w ufw status. Za pół roku inaczej już nie będziesz wiedzieć, po co otwarty jest port 8443.

Kolejne usługi dochodzą potem, na przykład serwer WWW:

ufw allow 80/tcp comment 'HTTP'
ufw allow 443/tcp comment 'HTTPS'

I dopiero teraz otwórz drugi terminal i zaloguj się na nowo. Dopiero gdy to logowanie się uda, sprawa jest załatwiona.

IPv6: druga rodzina adresów, o której się zapomina

Każdy współczesny serwer ma IPv6, i to zwykle bez tego, żeby ktokolwiek konfigurował to aktywnie. Kto myśli wyłącznie o IPv4, ma na koniec firewalla, który reguluje dokładnie połowę ruchu, a drugą połowę przepuszcza bez pytania. Sprawdź najpierw, czy globalne adresy IPv6 są w ogóle skonfigurowane:

ip -6 addr show scope global

Dobra wiadomość: na wszystkich czterech omawianych tu dystrybucjach w pliku /etc/default/ufw fabrycznie stoi IPV6=yes. UFW prowadzi wtedy równolegle regułę IPv6 do każdej reguły IPv4. Weryfikuj, zamiast ufać:

grep '^IPV6' /etc/default/ufw

Drugim, twardszym dowodem jest sama polityka domyślna łańcucha IPv6:

ip6tables -L INPUT -n

W pierwszym wierszu musi stać Chain INPUT (policy DROP). Jeśli widnieje tam policy ACCEPT, a poniżej nie ma łańcuchów ufw, to twój serwer jest przez IPv6 całkowicie otwarty, niezależnie od tego, jak dobrze wyglądają reguły IPv4.

Dwie pułapki:

  • Zmiana IPV6/etc/default/ufw nie zadziała przez ufw reload. Potrzebny jest ufw disable, a po nim ufw enable. Dokładnie w tej luce przez krótką chwilę nie masz żadnego firewalla, więc nie rób tego mimochodem na systemie wystawionym do sieci.
  • Kto blokuje ICMPv6 ryczałtem, niszczy własną łączność. Neighbor Discovery i „Packet too big” nie są przy IPv6 opcjonalne, tylko stanowią część protokołu. UFW zezwala na potrzebne typy już w /etc/ufw/before6.rules. Ruszaj ten plik wyłącznie wtedy, gdy dokładnie wiesz, co robisz.

Jeśli reguła oparta na porcie została poprawnie założona w obu rodzinach adresów, UFW przy dodawaniu zgłasza dwa wiersze: Rule added oraz Rule added (v6). Brak drugiego wiersza oznacza brak połowy ochrony. Wyjątkiem są reguły ograniczone źródłem: przy ufw allow from 203.0.113.10 to any port 22 proto tcp pojawia się wyłącznie Rule added, i tak właśnie ma być, bo do adresu źródłowego IPv4 nie ma odpowiednika IPv6.

Co UFW naprawdę zapisuje: nftables jako backend

Krąży tu sporo półprawd. Sytuacja na Debianie 12, Debianie 13, Ubuntu 22.04 i Ubuntu 24.04 jest jednolita: UFW nadal mówi składnią iptables, ale polecenie iptables jest na wszystkich czterech systemach narzędziem zgodności iptables-nft. Reguły lądują więc w podsystemie nftables jądra. Dowód w jednym wierszu:

iptables -V

Wynik kończy się na (nf_tables). Jeśli widnieje tam (legacy), twój system pracuje na starym backendzie. To wprawdzie działa, ale prowadzi do tego, że reguły z dwóch światów leżą w jądrze obok siebie i wzajemnie się przesłaniają. Który wariant jest ustawiony, pokazuje update-alternatives --display iptables.

Od strony nftables wygląda to tak. Ważne, żebyś zaglądał tam dopiero po włączeniu firewalla:

apt-get install -y nftables
nft list tables

Dopóki UFW nie jest aktywny, tabela w ogóle nie istnieje: iptables-nft zakłada ją dopiero wtedy, gdy faktycznie ładowane są reguły, czyli najwcześniej wraz z ufw --force enable. Wcześniej nft list tables pozostaje puste, a nft list table ip filter przerywa działanie komunikatem Error: No such file or directory. To nie jest usterka, tylko stan oczekiwany. Dopiero gdy na liście pojawią się table ip filter oraz table ip6 filter, warto zajrzeć do środka:

nft list table ip filter

Wynik zaczyna się wierszem Warning: table ip filter is managed by iptables-nft, do not touch!, i jest to napisane dosłownie: oglądać wolno, zmieniać ręcznie nie. Poniżej znajdziesz łańcuchy takie jak ufw-before-input, ufw-user-inputufw-after-input. To jest moment, w którym uwidacznia się najważniejszy konflikt: nie mieszaj UFW z ręcznie pisanymi regułami nft. Polecenie nft flush ruleset usuwa z jądra wszystkie reguły UFW, a UFW nic o tym nie wie. ufw status zgłasza potem nadal Status: active, podczas gdy faktycznie nie działa ani jedna reguła. To jedno z najbardziej nieprzyjemnych źródeł błędów w ogóle, bo narzędzie, którym sprawdzasz, cię okłamuje. Droga powrotna:

ufw reload

Dlatego po każdej ingerencji w inne narzędzia firewallowe (Docker, Kubernetes, oprogramowanie VPN, iptables-persistent) sprawdzaj nie status UFW, tylko rzeczywisty zestaw reguł w jądrze.

ufw limit przeciwko brute force, i gdzie się kończy

Dla SSH UFW oferuje ograniczanie tempa połączeń:

ufw limit 22/tcp comment 'SSH rate limit'

Semantyka jest jasno zdefiniowana w podręczniku: połączenia są zwyczajnie dopuszczane, ale zostają odrzucone, gdy tylko pojedynczy adres źródłowy nawiąże w ciągu 30 sekund sześć albo więcej nowych połączeń. Wartości są zaszyte na sztywno i nie da się ich zmienić przez interfejs UFW. Pod maską działa to na module recent, widocznym w iptables -S. Dla IPv6 UFW zakłada równoważną regułę, o ile moduł jądra jest dostępny, co ma miejsce na wszystkich czterech dystrybucjach.

Jeśli wcześniej ustawiłeś już ufw allow 22/tcp, powstaje teraz druga reguła. Stara musi zniknąć, inaczej zadziała jako pierwsza i ograniczenie trafi w próżnię:

ufw status numbered
ufw delete allow 22/tcp

Jeśli zamiast tego kasujesz po numerze (ufw delete 3), zwróć uwagę na dwie właściwości. Po pierwsze ufw status numbered numeruje reguły IPv4 i IPv6 w sposób ciągły, w jednej wspólnej liście, a po każdym skasowaniu przesuwają się wszystkie kolejne numery. Kasuj dlatego zawsze tylko jedną regułę i wypisuj listę na nowo, albo pracuj od najwyższego numeru w dół. Po drugie UFW pyta przy tym interaktywnie: Proceed with operation (y|n)?.

A teraz uczciwa ocena, której brakuje w większości poradników:

  • Przeciwko atakom rozproszonym to nie pomaga. Zliczanie idzie osobno dla każdego adresu źródłowego. Botnet z tysiącem adresów wykonuje po pięć prób na adres i pozostaje poniżej progu.
  • Trafia to w twoje własne automaty. Skrypt backupu z wieloma pojedynczymi wywołaniami rsync, przebieg Ansible z kilkoma forkami albo zadanie CI mogą wpaść w ten sam limit. Wtedy odcinasz nie atakującego, tylko własny potok wdrożeniowy. Dla takich źródeł lepiej postaw przed tym jawny wyjątek, na przykład ufw allow from 203.0.113.10 to any port 22 proto tcp z prawdziwym adresem twojego serwera budującego.
  • Nie zastępuje to porządnej konfiguracji SSH. Najskuteczniejszym krokiem przeciwko zgadywaniu haseł jest wyłączenie haseł: PasswordAuthentication no/etc/ssh/sshd_config względnie w pliku w katalogu /etc/ssh/sshd_config.d/. Kto nie przyjmuje haseł, ten nie da ich sobie odgadnąć. Uzupełniająco sensowny jest fail2ban, który w przeciwieństwie do ufw limit reaguje na wpisy w logach i blokuje na dłużej.

Po czym poznasz, że naprawdę zadziałało

„Polecenie wykonało się bez błędu” to żaden dowód. Cztery kontrole, które faktycznie coś mówią:

Po pierwsze stan całościowy.

ufw status verbose

Oczekiwany jest wynik w takiej postaci:

Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp                     LIMIT IN    Anywhere
22/tcp (v6)                LIMIT IN    Anywhere (v6)

Rozstrzygający jest drugi wiersz z dopiskiem (v6). Bez niego brakuje pokrycia dla IPv6.

Po drugie restart. Firewall, który nie przetrwa restartu, jest bezwartościowy.

systemctl is-enabled ufw

Odpowiedź musi brzmieć enabled. A potem faktycznie zrestartuj serwer i zaloguj się. To jedyny test, który naprawdę odpowiada na to pytanie.

Po trzecie spojrzenie z zewnątrz. Sprawdź z innego hosta, czy celowo nieotwarty port jest naprawdę zamknięty, na przykład poleceniem nc -zv TWOJ-IP 3306. Ważne: test z localhost nie dowodzi zupełnie niczego, bo ruch przez interfejs loopback UFW zasadniczo przepuszcza.

Po czwarte logi. Tu występuje realna różnica między dystrybucjami. W ustawieniu domyślnym low UFW protokołuje zablokowane pakiety przez log jądra. Na Ubuntu 22.04 i 24.04 rsyslog jest obecny, komunikaty lądują dodatkowo w /var/log/ufw.log. Na Debianie 12, a zwłaszcza na Debianie 13, w instalacjach minimalnych brakuje rsysloga, więc ten plik po prostu tam nie istnieje. Droga, która działa wszędzie:

journalctl -k -n 50

Szukane są wiersze zaczynające się od [UFW BLOCK]. Jeśli chcesz widzieć więcej, podkręć poziom (ufw logging medium), a potem wróć z powrotem na ufw logging low. Na serwerze z ruchem publicznym wyższy poziom zapełnia dysk szybciej, niż się wydaje.

Komunikaty błędów w brzmieniu dosłownym

ERROR: problem running ufw-init: najczęstszą przyczyną jest konflikt z drugim narzędziem firewallowym, zwykle nftables.service albo iptables-persistent, ewentualnie pomieszanie backendu legacy i nft. Sprawdź iptables -V i wyłącz konkurujące usługi. UFW dostarcza poza tym skrypt kontrolny, który przechodzi wymagania jądra po kolei i zgłasza, które wymaganie modułu zawodzi.

ERROR: Could not find a profile matching 'OpenSSH': brakuje profilu aplikacji, bo openssh-server nie jest zainstalowany albo plik w katalogu /etc/ufw/applications.d/ został usunięty. Na Ubuntu ten katalog bez zainstalowanych usług i tak jest pusty. Użyj zamiast tego numeru portu.

ERROR: Bad port: najczęściej literówka albo nazwa usługi, której /etc/services nie zna. Numery portów są zawsze jednoznaczne.

Skipping adding existing rule względnie Skipping adding existing rule (v6): to nie komunikat błędu, tylko informacja, że reguła już istnieje. Jeśli wydaje ci się, że zmieniłeś regułę, a ona pozostaje bez zmian, to właśnie jest powód.

ERROR: Invalid position '0': przy kasowaniu i wstawianiu UFW liczy od 1, a nie od 0. Numery pochodzą z ufw status numbered i przesuwają się po każdym skasowaniu. Kasuj dlatego zawsze od najwyższego numeru w dół.

WARN: Rules updated but not applied: reguła leży w konfiguracji, ale firewall jest nieaktywny. Brakuje ufw enable.

Różnice między dystrybucjami w skrócie

  • Debian 13 (trixie): UFW trzeba doinstalować. Backend nf_tables. IPV6=yes fabrycznie. W instalacjach minimalnych brakuje rsysloga, logi więc przez journalctl -k. SSH przez ssh.service.
  • Debian 12 (bookworm): UFW trzeba doinstalować. Backend nf_tables. IPV6=yes fabrycznie. rsyslog obecny zależnie od wariantu instalacji, /var/log/ufw.log nie jest więc gwarantowany. SSH przez ssh.service.
  • Ubuntu 24.04 LTS: UFW obecny w obrazach serwerowych, ale nieaktywny. Backend nf_tables. IPV6=yes fabrycznie. /var/log/ufw.log obecny. SSH przez aktywację socketem, czyli ssh.socket, dlatego nasłuchujący port sprawdzaj zawsze poleceniem sudo ss -lntp | grep sshd, a nie przez sshd -T.
  • Ubuntu 22.04 LTS: UFW obecny w obrazach serwerowych, ale nieaktywny. Backend nf_tables. IPV6=yes fabrycznie. /var/log/ufw.log obecny. SSH przez ssh.service.

Co jest takie samo na wszystkich czterech systemach: UFW po instalacji jest zawsze nieaktywny. Nikt nie włącza ci firewalla po cichu i nikt go po cichu nie wyłącza.

Docker obchodzi UFW

Jeśli na serwerze działa Docker, obowiązuje ważne ograniczenie: opublikowane porty kontenerów ignorują twoje reguły UFW. Docker zakłada własne łańcuchy i pracuje z translacją adresu docelowego, przez co pakiety omijają łańcuchy UFW w INPUT. Kontener uruchomiony przez docker run -p 8080:80 jest więc osiągalny z zewnątrz, chociaż ufw status pokazuje czyste „deny incoming”.

Najprostszym i najbardziej odpornym środkiem zaradczym jest w ogóle nie publikować na wszystkich adresach, tylko wyłącznie lokalnie, a dostęp prowadzić przez reverse proxy:

docker run -d -p 127.0.0.1:8080:80 nginx

W pliku Compose odpowiada temu zapis portu "127.0.0.1:8080:80". Alternatywnie istnieje możliwość wpięcia własnych reguł do zarezerwowanego przez Dockera łańcucha DOCKER-USER. To jest skuteczne, ale pracochłonne w utrzymaniu i wymaga ponownego sprawdzenia przy każdej aktualizacji Dockera. Podpięcie pod 127.0.0.1 rozwiązuje problem u źródła.

Jeśli jednak odciąłeś sobie dostęp

Stało się, SSH już nie odpowiada. Po kolei:

  1. Nie restartuj. Restart nie pomoże, bo UFW jest włączony jako usługa systemd i odtwarza swoje reguły przy starcie. Serwer wróci dokładnie tak samo zamknięty, jak został wyłączony.
  2. Otwórz konsolę VNC w panelu klienta i zaloguj się tam jako root.
  3. Wyłącz firewalla: ufw disable. Tym samym wracasz do gry, ale też z powrotem bez ochrony.
  4. Znajdź przyczynę, nie zgaduj. Obejrzyj ufw status numbered oraz rzeczywisty port SSH z ss -lntup. W dziewięciu przypadkach na dziesięć przyczyną jest jedna z tych trzech: nigdy nie było reguły zezwalającej dla SSH, reguła stoi na porcie 22, podczas gdy sshd nasłuchuje na innym porcie, albo otwarcie było ograniczone do adresu IP, którego twoje łącze już nie ma (dynamiczne przydzielanie adresów na łączu internetowym).
  5. Popraw i włącz na nowo, tym razem we właściwej kolejności i z ustawionym wyłącznikiem awaryjnym.

Jeśli chcesz całkowicie zresetować zestaw reguł, jest ufw reset. Warto wiedzieć: to polecenie dezaktywuje firewalla i odkłada kopie zapasowe dotychczasowych plików reguł w /etc/ufw/, ze znacznikiem czasu w nazwie pliku. W razie wątpliwości możesz więc sprawdzić, co obowiązywało wcześniej. Nigdy nie wykonuj go przez połączenie SSH bez otwartej obok konsoli.

Sensowna konfiguracja wyjściowa

Dla typowego serwera WWW pełna sekwencja wygląda tak:

apt-get update
apt-get install -y ufw
ufw default deny incoming
ufw default allow outgoing
ufw limit 22/tcp comment 'SSH rate limit'
ufw allow 80/tcp comment 'HTTP'
ufw allow 443/tcp comment 'HTTPS'
ufw --force enable
ufw status verbose

Zwróć uwagę, że wprawdzie default deny incoming stoi tu przed regułą dla SSH, ale włączenie następuje na samym końcu. Dopóki UFW jest nieaktywny, polityka domyślna nie wyrządza żadnej szkody. Krytyczny jest wyłącznie stan w momencie enable, a w tej chwili reguła dla SSH jest już dawno zapisana.

Kto chce dodatkowo udostępnić dostępy administracyjne wyłącznie z własnej sieci, pracuje z regułami ograniczonymi źródłem według wzorca ufw allow from 203.0.113.0/24 to any port 22 proto tcp. Jeszcze czyściej jest w ogóle nie wystawiać usług administracyjnych do otwartej sieci, tylko podpiąć je przez VPN. Instancję WireGuard postawisz na każdym z tych czterech systemów w kilka minut, a zastępuje ona cały stos wyjątków w firewallu jednym otwartym portem UDP.

I na koniec ocena, którą warto sobie uświadomić: UFW filtruje na samym serwerze. Przeciwko atakom wolumetrycznym, które wysycają łącze, z zasady nie pomaga, bo pakiety przeszły już przez łącze w chwili, gdy twoje jądro je odrzuca. Do tego potrzebne jest filtrowanie w sieci przed serwerem. W KernelHost przejmuje to infrastruktura ustawiona przed serwerem w centrum danych maincubes we Frankfurcie nad Menem, z filtrowaniem Arbor w czasie rzeczywistym. Twój lokalny firewall i ochrona sieciowa rozwiązują dwa różne problemy, i potrzebujesz obu.

Najczęstsze pytania

Czy „ufw enable” natychmiast odetnie mnie od trwającej sesji SSH?
Nie, i właśnie na tym polega pułapka. UFW zezwala w /etc/ufw/before.rules na już istniejące połączenia (stan RELATED,ESTABLISHED). Twoja bieżąca sesja przeżywa więc włączenie nawet wtedy, gdy żadna reguła dla SSH w ogóle nie istnieje. Dopiero kolejna próba nawiązania połączenia kończy się niepowodzeniem. Sprawdzaj dlatego zawsze drugą, świeżo nawiązaną sesją, zanim zamkniesz pierwszą.
Czy muszę włączać IPv6 w UFW osobno?
Na Debianie 13, Debianie 12, Ubuntu 24.04 i Ubuntu 22.04 wpis IPV6=yes stoi fabrycznie w /etc/default/ufw. UFW zakłada wtedy do każdej reguły automatycznie odpowiednik IPv6, rozpoznasz to po komunikacie „Rule added (v6)” i po dopisku „(v6)” w ufw status. Twardo sprawdzisz to poleceniem ip6tables -L INPUT -n: musi tam stać „policy DROP”. Zmiana IPV6 zadziała dopiero po ufw disable, a potem ufw enable, samo ufw reload nie wystarczy.
Czy UFW korzysta z iptables, czy z nftables?
Poniekąd z obu. UFW nadal mówi składnią iptables, ale polecenie iptables jest na wszystkich czterech dystrybucjach warstwą zgodności iptables-nft. Reguły lądują więc w podsystemie nftables jądra i przy aktywnym firewallu są widoczne przez nft list table ip filter. Dopóki UFW nie jest jeszcze włączony, ta tabela w ogóle nie istnieje, a polecenie zgłasza „Error: No such file or directory”. Backend sprawdzisz przez iptables -V, wynik kończy się na (nf_tables). Nie mieszaj UFW z ręcznie pisanymi regułami nft: nft flush ruleset usuwa wszystkie reguły UFW, podczas gdy ufw status nadal zgłasza „active”.
Co dokładnie robi ufw limit?
ufw limit zwyczajnie dopuszcza połączenia, ale je odrzuca, gdy tylko pojedynczy adres źródłowy nawiąże w ciągu 30 sekund sześć albo więcej nowych połączeń. Wartości są stałe i nie da się ich zmienić przez interfejs UFW. Przeciwko atakom rozproszonym to nie pomaga, bo zliczanie idzie osobno dla każdego adresu źródłowego. Poza tym może trafić we własne automaty, na przykład skrypty backupu albo zadania CI z wieloma równoległymi połączeniami SSH. Dla takich źródeł załóż przed tym jawny wyjątek.
Nie mogę się już dostać na serwer przez SSH. Czy pomoże restart?
Nie. UFW jest włączony jako usługa systemd i odtwarza swoje reguły przy starcie, więc serwer wróci dokładnie tak samo zamknięty. Skorzystaj zamiast tego z konsoli VNC w panelu klienta, zaloguj się tam jako root i wykonaj ufw disable. Potem szukaj przyczyny: brakująca reguła dla SSH, zły port albo ograniczenie źródła do adresu IP, którego twoje łącze już nie ma.
Dlaczego moje kontenery Dockera są osiągalne z zewnątrz mimo aktywnego firewalla UFW?
Docker zakłada własne łańcuchy i pracuje z translacją adresu docelowego, przez co opublikowane porty kontenerów omijają łańcuchy UFW. Ustawienie „deny incoming” dla tego ruchu nie działa. Najbardziej odpornym rozwiązaniem jest publikowanie portów wyłącznie lokalnie, czyli -p 127.0.0.1:8080:80 zamiast -p 8080:80, a dostęp prowadzić przez reverse proxy.
Dlaczego na moim serwerze z Debianem nie ma /var/log/ufw.log?
Bo nie jest tam zainstalowany rsyslog. Debian 13 w instalacjach minimalnych nie dostarcza już żadnego demona syslog i zdaje się na systemd-journald, Debian 12 zależnie od wariantu instalacji również nie. Komunikaty mimo to są, odczytasz je przez journalctl -k i szukasz wierszy z [UFW BLOCK]. Na Ubuntu 22.04 i 24.04 rsyslog jest obecny, tam ten plik istnieje.

UFW Firewall Linux Debian Ubuntu nftables IPv6 SSH Bezpieczeństwo serwera Serwer root