UFW-Firewall einrichten, ohne sich selbst auszusperren

Veröffentlicht am 16 Min. Lesezeit

Die richtige Reihenfolge beim UFW-Aufbau, IPv6-Regeln, nftables als Backend, Ratenbegrenzung per ufw limit und der Rettungsweg über die Konsole, wenn es doch schiefgeht.

Ein Paketfilter ist auf einem Root Server keine Kür, sondern Grundausstattung. UFW (Uncomplicated Firewall) macht das angenehm einfach, hat aber eine Eigenschaft, die jedes Jahr tausende Administratoren aus ihren eigenen Servern aussperrt: Der Befehl, der die Firewall scharfschaltet, ist derselbe, der die laufende SSH-Sitzung kappen kann. Diese Anleitung zeigt die Reihenfolge, bei der das nicht passiert, und, fast noch wichtiger, den Weg zurück, falls es doch passiert.

Alle Angaben beziehen sich auf Debian 13 (trixie), Debian 12 (bookworm), Ubuntu 24.04 LTS und Ubuntu 22.04 LTS. Die Befehle sind für den Betrieb als root geschrieben. Wenn Sie als normaler Benutzer arbeiten, stellen Sie jedem Befehl sudo voran.

Warum die Reihenfolge über alles entscheidet

Der klassische Fehler sieht so aus: Jemand setzt zuerst die Standardrichtlinie auf "alles eingehende verwerfen", schaltet die Firewall ein und will danach in Ruhe die SSH-Regel nachtragen. Genau dazwischen liegt das Zeitfenster, in dem der Server aufhört, erreichbar zu sein.

Der Grund, warum dieser Fehler so oft unbemerkt bleibt, ist tückischer als der Fehler selbst. UFW bringt in /etc/ufw/before.rules eine Regel mit, die bereits bestehende Verbindungen durchlässt:

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

Ihre aktuelle SSH-Sitzung ist eine bestehende Verbindung. Sie überlebt das Einschalten der Firewall also auch dann, wenn überhaupt keine SSH-Regel existiert. Der Prompt bleibt da, alles wirkt in Ordnung. Erst der nächste Verbindungsversuch, also typischerweise Ihr Login am nächsten Morgen, läuft in einen Timeout. Deshalb gilt: Solange die Firewall nicht mit einer zweiten, frisch aufgebauten Sitzung verifiziert ist, verlassen Sie die erste Sitzung nicht.

Faustregel: erst erlauben, dann verwerfen, dann einschalten, dann mit einer zweiten Sitzung prüfen, und erst danach die erste Sitzung schließen.

Vor dem ersten Befehl: Rettungsweg und Bestandsaufnahme

Bevor Sie irgendetwas an der Paketfilterung ändern, klären Sie zwei Dinge.

1. Wie kommen Sie ohne SSH auf den Server?

Bei KVM-Rootservern und Dedicated Servern von KernelHost erreichen Sie die VNC-Konsole direkt im Kundenbereich. Diese Konsole hängt nicht am Netzwerkstack des Gastsystems, sondern an der Virtualisierungsschicht beziehungsweise am Netzwerkanschluss selbst. Eine Firewall-Regel im Gast kann sie deshalb nicht blockieren. Melden Sie sich einmal vorher über diese Konsole an und vergewissern Sie sich, dass Sie das root-Passwort kennen. Ein Rettungsweg, den man erst im Notfall zum ersten Mal ausprobiert, ist kein Rettungsweg.

2. Was lauscht überhaupt auf diesem Server?

Regeln für Dienste, die es nicht gibt, sind harmlos. Ein fehlender Dienst, den Sie übersehen haben, kostet Sie den Zugang oder einen Ausfall. Verschaffen Sie sich einen Überblick:

ss -lntup

Die Spalte Local Address:Port unterscheidet dabei sauber zwischen 0.0.0.0:22 (nur IPv4), [::]:22 (IPv6 und über den Dual-Stack-Socket meist auch IPv4) und 127.0.0.1:3306 (nur lokal, braucht keine Firewall-Regel). Alles, was auf 127.0.0.1 oder ::1 gebunden ist, muss nicht freigegeben werden.

Ganz besonders wichtig ist der tatsächliche SSH-Port. Nicht raten, nachsehen. Der Befehl braucht Leserechte auf die Hostkeys, läuft also als root beziehungsweise mit sudo:

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

Ein Detail, das viele Anleitungen unterschlagen: Unter Ubuntu 24.04 wird der SSH-Dienst per Socket-Aktivierung über ssh.socket gestartet, nicht über ssh.service. Dort meldet systemctl is-enabled ssh.socket ein enabled und ssh.service ein disabled. Auf Debian 12, Debian 13 und Ubuntu 22.04 ist es genau umgekehrt, dort gilt der klassische Dauerdienst.

Die Folge ist für dieses Thema unangenehm konkret: Auf Ubuntu 24.04 ist der Port, den sshd -T meldet, nicht zwingend der Port, auf dem tatsächlich gelauscht wird. Maßgeblich ist dort ListenStream in /lib/systemd/system/ssh.socket beziehungsweise in einer Ergänzungsdatei unter /etc/systemd/system/ssh.socket.d/. Wer seinen SSH-Port geändert hat und sich auf sshd -T verlässt, gibt in UFW die falsche Portnummer frei und sperrt sich beim nächsten Login aus. Verlässlich ist auf allen vier Systemen nur der Blick auf den Prozess, der wirklich lauscht:

sudo ss -lntp | grep sshd

3. Der Totmannschalter

Für den Fall, dass etwas schiefgeht, legen Sie sich vor der riskanten Änderung einen Zeitschalter an, der die Firewall nach zehn Minuten von selbst wieder abschaltet:

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

Wenn alles funktioniert hat, brechen Sie ihn ab:

pkill -f 'sleep 600; ufw disable'

Das pkill trifft nur den umschließenden Shell-Prozess. Der sleep läuft als Waise weiter und endet folgenlos, weil niemand mehr da ist, der danach ufw disable aufrufen könnte.

Die Reihenfolge, die nicht aussperrt

Unter Debian ist UFW in der Regel nicht vorinstalliert, unter Ubuntu Server meist schon. Installieren schadet in keinem Fall:

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

Jetzt die Reihenfolge, und zwar genau so:

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

Vier Punkte dazu:

  • Die Erlaubnisregel steht vor allem anderen. UFW nimmt Regeln auch im inaktiven Zustand entgegen und speichert sie in /etc/ufw/user.rules. Beim Einschalten sind sie sofort da.
  • Statt 22/tcp können Sie ein Anwendungsprofil verwenden, etwa ufw allow OpenSSH. Verlassen Sie sich darauf aber nicht blind: Die Profile stammen nicht von UFW selbst, sondern aus den installierten Paketen. Unter Ubuntu ist /etc/ufw/applications.d/ ohne installierte Dienste leer, ufw app list gibt dort nur die Überschrift Available applications: und keinen einzigen Eintrag aus. Unter Debian bringt schon das ufw-Paket rund 38 Profile mit, dort heißt das SSH-Profil SSH. Das Profil OpenSSH stammt auf beiden Distributionen aus dem Paket openssh-server, auf Servern also der Normalfall. Bei einem abweichenden SSH-Port geht das Profil ohnehin ins Leere. Welche Profile Ihr System kennt, zeigt ufw app list; die portbasierte Schreibweise ufw allow 22/tcp funktioniert dagegen auf allen vier Systemen identisch und ist deshalb die verlässlichere Wahl.
  • ufw enable fragt interaktiv nach: Command may disrupt existing ssh connections. Proceed with operation (y|n)?. In Skripten und in Ansible-Rollen nehmen Sie ufw --force enable, sonst hängt der Lauf.
  • Der Kommentar hinter comment taucht in ufw status auf. In einem halben Jahr wissen Sie sonst nicht mehr, wofür Port 8443 offen ist.

Weitere Dienste kommen danach dazu, zum Beispiel ein Webserver:

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

Und erst jetzt öffnen Sie ein zweites Terminal und melden sich neu an. Erst wenn dieser Login klappt, ist die Sache erledigt.

IPv6: die zweite Adressfamilie, die man vergisst

Jeder moderne Server hat IPv6, und zwar meistens ohne, dass jemand das aktiv eingerichtet hätte. Wer nur an IPv4 denkt, hat am Ende eine Firewall, die genau die Hälfte des Verkehrs regelt und die andere Hälfte durchwinkt. Prüfen Sie zuerst, ob überhaupt globale IPv6-Adressen konfiguriert sind:

ip -6 addr show scope global

Die gute Nachricht: Auf allen vier hier behandelten Distributionen steht in /etc/default/ufw ab Werk IPV6=yes. UFW pflegt dann parallel eine IPv6-Regel zu jeder IPv4-Regel. Verifizieren statt vertrauen:

grep '^IPV6' /etc/default/ufw

Ein zweiter, härterer Beweis ist die Standardrichtlinie der IPv6-Kette selbst:

ip6tables -L INPUT -n

In der ersten Zeile muss Chain INPUT (policy DROP) stehen. Steht dort policy ACCEPT und darunter keine ufw-Ketten, dann ist Ihr Server über IPv6 vollständig offen, egal wie gut die IPv4-Regeln aussehen.

Zwei Fallstricke:

  • Eine Änderung an IPV6 in /etc/default/ufw wirkt nicht durch ufw reload. Es braucht ufw disable gefolgt von ufw enable. Genau in dieser Lücke haben Sie kurzzeitig keine Firewall, also machen Sie das nicht auf einem exponierten System nebenbei.
  • Wer ICMPv6 pauschal blockiert, zerstört seine eigene Konnektivität. Neighbor Discovery und "Packet too big" sind bei IPv6 nicht optional, sondern Teil des Protokolls. UFW erlaubt die notwendigen Typen bereits in /etc/ufw/before6.rules. Fassen Sie diese Datei nur an, wenn Sie genau wissen, was Sie tun.

Wenn eine portbasierte Regel korrekt in beiden Adressfamilien angelegt wurde, meldet UFW beim Hinzufügen zwei Zeilen: Rule added und Rule added (v6). Fehlt die zweite Zeile, fehlt der halbe Schutz. Eine Ausnahme sind quellbeschränkte Regeln: Bei ufw allow from 203.0.113.10 to any port 22 proto tcp erscheint nur Rule added, und das ist richtig so, denn zu einer IPv4-Quelladresse gibt es keine IPv6-Entsprechung.

Was UFW wirklich schreibt: nftables als Backend

Hier gibt es viel Halbwissen. Die Lage auf Debian 12, Debian 13, Ubuntu 22.04 und Ubuntu 24.04 ist einheitlich: UFW spricht weiterhin die iptables-Syntax, aber der Befehl iptables ist auf allen vier Systemen das Kompatibilitätswerkzeug iptables-nft. Die Regeln landen also im nftables-Subsystem des Kernels. Der Beweis in einer Zeile:

iptables -V

Die Ausgabe endet mit (nf_tables). Steht dort (legacy), arbeitet Ihr System mit dem alten Backend. Das funktioniert zwar, führt aber dazu, dass Regeln aus zwei Welten nebeneinander im Kernel liegen und sich gegenseitig überdecken. Welche Variante eingestellt ist, zeigt update-alternatives --display iptables.

Von der nftables-Seite aus betrachtet sieht das so aus. Wichtig ist, dass Sie erst nach dem Einschalten der Firewall nachsehen:

apt-get install -y nftables
nft list tables

Solange UFW nicht aktiv ist, existiert die Tabelle nämlich gar nicht: iptables-nft legt sie erst an, wenn tatsächlich Regeln geladen werden, also frühestens mit ufw --force enable. Vorher bleibt nft list tables leer und ein nft list table ip filter bricht mit Error: No such file or directory ab. Das ist kein Defekt, sondern der erwartete Zustand. Erst wenn in der Liste table ip filter und table ip6 filter auftauchen, lohnt der Blick hinein:

nft list table ip filter

Die Ausgabe beginnt mit der Zeile Warning: table ip filter is managed by iptables-nft, do not touch!, und die ist wörtlich gemeint: ansehen ja, von Hand ändern nein. Darunter finden Sie Ketten wie ufw-before-input, ufw-user-input und ufw-after-input. Das ist der Punkt, an dem der wichtigste Konflikt sichtbar wird: Mischen Sie nicht UFW und handgeschriebene nft-Regeln. Ein nft flush ruleset löscht sämtliche UFW-Regeln aus dem Kernel, ohne dass UFW davon etwas mitbekommt. ufw status meldet danach weiterhin Status: active, während faktisch keine einzige Regel greift. Das ist eine der unangenehmsten Fehlerquellen überhaupt, weil das Werkzeug, mit dem Sie prüfen, Sie belügt. Der Weg zurück:

ufw reload

Prüfen Sie deshalb nach jedem Eingriff an anderen Firewall-Werkzeugen (Docker, Kubernetes, VPN-Software, iptables-persistent) nicht den UFW-Status, sondern den tatsächlichen Kernel-Regelsatz.

ufw limit gegen Brute-Force, und wo es aufhört

Für SSH bietet UFW eine Ratenbegrenzung an:

ufw limit 22/tcp comment 'SSH rate limit'

Die Semantik ist im Handbuch klar definiert: Verbindungen werden normal erlaubt, aber verworfen, sobald eine einzelne Quell-IP innerhalb von 30 Sekunden sechs oder mehr neue Verbindungen aufbaut. Die Werte sind fest verdrahtet und lassen sich über die UFW-Oberfläche nicht ändern. Unter der Haube arbeitet das mit dem recent-Modul, sichtbar in iptables -S. Für IPv6 legt UFW eine gleichwertige Regel an, sofern das Kernel-Modul verfügbar ist, was auf allen vier Distributionen der Fall ist.

Wenn Sie vorher schon ufw allow 22/tcp gesetzt haben, entsteht jetzt eine zweite Regel. Die alte muss weg, sonst greift sie zuerst und die Begrenzung läuft ins Leere:

ufw status numbered
ufw delete allow 22/tcp

Wenn Sie stattdessen über die Nummer löschen (ufw delete 3), beachten Sie zwei Eigenheiten. Erstens nummeriert ufw status numbered IPv4- und IPv6-Regeln durchlaufend in einer einzigen Liste, und nach jedem Löschvorgang verschieben sich sämtliche folgenden Nummern. Löschen Sie deshalb immer nur eine Regel, lassen Sie sich die Liste danach neu ausgeben, oder arbeiten Sie von der höchsten Nummer abwärts. Zweitens fragt UFW dabei interaktiv nach: Proceed with operation (y|n)?.

Und jetzt die ehrliche Einordnung, die in den meisten Anleitungen fehlt:

  • Gegen verteilte Angriffe hilft es nicht. Die Zählung läuft pro Quell-IP. Ein Botnetz mit tausend Adressen macht pro Adresse fünf Versuche und bleibt unter der Schwelle.
  • Es trifft Ihre eigenen Automatismen. Ein Backup-Skript mit vielen einzelnen rsync-Aufrufen, eine Ansible-Ausführung mit mehreren Forks oder ein CI-Job können in dieselbe Grenze laufen. Dann sperren Sie nicht den Angreifer aus, sondern Ihre eigene Deployment-Pipeline. Für solche Quellen legen Sie besser eine explizite Ausnahme davor, zum Beispiel ufw allow from 203.0.113.10 to any port 22 proto tcp mit der echten Adresse Ihres Build-Servers.
  • Es ersetzt keine saubere SSH-Konfiguration. Der wirksamste Schritt gegen Passwort-Raten ist, Passwörter abzuschalten: PasswordAuthentication no in /etc/ssh/sshd_config beziehungsweise in einer Datei unter /etc/ssh/sshd_config.d/. Wer keine Passwörter annimmt, kann sie auch nicht erraten lassen. Ergänzend ist fail2ban sinnvoll, das im Gegensatz zu ufw limit auf Logeinträge reagiert und länger sperrt.

Woran Sie erkennen, dass es wirklich funktioniert hat

"Der Befehl lief ohne Fehler durch" ist kein Nachweis. Vier Prüfungen, die tatsächlich etwas aussagen:

Erstens der Gesamtzustand.

ufw status verbose

Erwartet wird eine Ausgabe in dieser Form:

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)

Entscheidend ist die zweite Zeile mit dem Zusatz (v6). Ohne sie fehlt die IPv6-Abdeckung.

Zweitens der Neustart. Eine Firewall, die einen Reboot nicht übersteht, ist wertlos.

systemctl is-enabled ufw

Die Antwort muss enabled lauten. Und dann starten Sie den Server tatsächlich einmal neu und melden sich an. Das ist der einzige Test, der die Frage wirklich beantwortet.

Drittens der Blick von außen. Prüfen Sie von einem anderen Host aus, ob ein absichtlich nicht freigegebener Port wirklich zu ist, zum Beispiel mit nc -zv IHRE-IP 3306. Wichtig: Ein Test von localhost aus beweist gar nichts, weil Verkehr über das Loopback-Interface von UFW grundsätzlich durchgelassen wird.

Viertens die Logs. Hier gibt es einen echten Unterschied zwischen den Distributionen. UFW protokolliert in der Voreinstellung low blockierte Pakete über das Kernel-Log. Unter Ubuntu 22.04 und 24.04 ist rsyslog vorhanden, die Meldungen landen zusätzlich in /var/log/ufw.log. Unter Debian 12 und ganz besonders unter Debian 13 fehlt rsyslog in minimalen Installationen, dort existiert diese Datei schlicht nicht. Der Weg, der überall funktioniert:

journalctl -k -n 50

Gesucht sind Zeilen, die mit [UFW BLOCK] beginnen. Wenn Sie mehr sehen wollen, drehen Sie die Stufe hoch (ufw logging medium) und danach wieder zurück auf ufw logging low. Auf einem Server mit Publikumsverkehr füllt die höhere Stufe die Platte schneller, als man denkt.

Fehlermeldungen im Wortlaut

ERROR: problem running ufw-init: Der häufigste Auslöser ist ein Konflikt mit einem zweiten Firewall-Werkzeug, meist nftables.service oder iptables-persistent, oder eine Vermischung von Legacy- und nft-Backend. Prüfen Sie iptables -V und schalten Sie konkurrierende Dienste ab. UFW liefert außerdem ein Prüfskript mit, das die Kernel-Voraussetzungen einzeln durchgeht und meldet, welche Modul-Anforderung fehlschlägt.

ERROR: Could not find a profile matching 'OpenSSH': Das Anwendungsprofil fehlt, weil openssh-server nicht installiert ist oder die Datei unter /etc/ufw/applications.d/ entfernt wurde. Unter Ubuntu ist dieses Verzeichnis ohne installierte Dienste ohnehin leer. Verwenden Sie stattdessen die Portnummer.

ERROR: Bad port: Meist ein Tippfehler oder ein Dienstname, den /etc/services nicht kennt. Portnummern sind immer eindeutig.

Skipping adding existing rule beziehungsweise Skipping adding existing rule (v6): Keine Fehlermeldung, sondern der Hinweis, dass die Regel schon da ist. Wenn Sie eine Regel geändert glauben, sie aber unverändert bleibt, ist das der Grund.

ERROR: Invalid position '0': Beim Löschen und Einfügen zählt UFW ab 1, nicht ab 0. Die Nummern stammen aus ufw status numbered und verschieben sich nach jedem Löschvorgang. Löschen Sie deshalb immer von der höchsten Nummer abwärts.

WARN: Rules updated but not applied: Die Regel liegt in der Konfiguration, aber die Firewall ist inaktiv. Ein ufw enable fehlt.

Distributionsunterschiede auf einen Blick

  • Debian 13 (trixie): UFW nachinstallieren. Backend nf_tables. IPV6=yes ab Werk. rsyslog fehlt in minimalen Installationen, Logs deshalb über journalctl -k. SSH über ssh.service.
  • Debian 12 (bookworm): UFW nachinstallieren. Backend nf_tables. IPV6=yes ab Werk. rsyslog je nach Installationsvariante vorhanden, /var/log/ufw.log also nicht garantiert. SSH über ssh.service.
  • Ubuntu 24.04 LTS: UFW auf Server-Abbildern vorhanden, aber inaktiv. Backend nf_tables. IPV6=yes ab Werk. /var/log/ufw.log vorhanden. SSH per Socket-Aktivierung über ssh.socket, deshalb den lauschenden Port immer mit sudo ss -lntp | grep sshd prüfen und nicht mit sshd -T.
  • Ubuntu 22.04 LTS: UFW auf Server-Abbildern vorhanden, aber inaktiv. Backend nf_tables. IPV6=yes ab Werk. /var/log/ufw.log vorhanden. SSH über ssh.service.

Was auf allen vier Systemen gleich ist: UFW ist nach der Installation immer inaktiv. Niemand schaltet Ihnen die Firewall heimlich ein, und niemand schaltet sie heimlich aus.

Docker hebelt UFW aus

Wenn auf dem Server Docker läuft, gilt eine wichtige Einschränkung: Veröffentlichte Container-Ports ignorieren Ihre UFW-Regeln. Docker legt eigene Ketten an und arbeitet mit Zieladressumsetzung, sodass die Pakete an den UFW-Ketten in INPUT vorbeilaufen. Ein docker run -p 8080:80 ist also von außen erreichbar, obwohl ufw status ein sauberes "deny incoming" zeigt.

Die einfachste und robusteste Gegenmaßnahme ist, gar nicht erst auf alle Adressen zu veröffentlichen, sondern nur lokal, und den Zugriff über einen Reverse Proxy zu führen:

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

In einer Compose-Datei entspricht das der Portangabe "127.0.0.1:8080:80". Alternativ existiert die Möglichkeit, UFW über eigene Regeln in die von Docker reservierte Kette DOCKER-USER einzuhängen. Das ist wirksam, aber wartungsintensiv und bei jedem Docker-Update erneut zu prüfen. Die Bindung an 127.0.0.1 löst das Problem an der Wurzel.

Wenn Sie doch ausgesperrt sind

Es ist passiert, SSH antwortet nicht mehr. Der Reihe nach:

  1. Nicht neu starten. Ein Reboot hilft nicht, denn UFW ist als systemd-Dienst aktiviert und stellt seine Regeln beim Hochfahren wieder her. Der Server kommt genauso verschlossen zurück, wie er heruntergefahren ist.
  2. VNC-Konsole im Kundenbereich öffnen und dort als root anmelden.
  3. Firewall abschalten: ufw disable. Damit sind Sie wieder im Spiel, aber eben auch wieder ungeschützt.
  4. Ursache finden, nicht raten. Sehen Sie sich ufw status numbered und den tatsächlichen SSH-Port aus ss -lntup an. In neun von zehn Fällen ist die Ursache eine dieser drei: Es gab nie eine Erlaubnisregel für SSH, die Regel steht auf Port 22, während sshd auf einem anderen Port lauscht, oder die Freigabe war auf eine IP-Adresse eingeschränkt, die Ihr Anschluss inzwischen nicht mehr hat (dynamische Adressvergabe beim Internetanschluss).
  5. Korrigieren und neu einschalten, diesmal in der richtigen Reihenfolge und mit gesetztem Totmannschalter.

Falls Sie den Regelsatz komplett zurücksetzen wollen, gibt es ufw reset. Wichtig zu wissen: Dieser Befehl deaktiviert die Firewall und legt Sicherungskopien der bisherigen Regeldateien unter /etc/ufw/ mit Zeitstempel im Dateinamen ab. Sie können also im Zweifel nachlesen, was vorher galt. Führen Sie ihn niemals über eine SSH-Verbindung aus, ohne dass die Konsole daneben offen ist.

Eine sinnvolle Ausgangskonfiguration

Für einen typischen Webserver sieht die vollständige Sequenz so aus:

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

Beachten Sie, dass hier zwar default deny incoming vor der SSH-Regel steht, das Einschalten aber ganz am Ende passiert. Solange UFW inaktiv ist, richtet die Standardrichtlinie keinen Schaden an. Kritisch ist ausschließlich der Zustand im Moment des enable, und zu diesem Zeitpunkt ist die SSH-Regel längst hinterlegt.

Wer darüber hinaus Verwaltungszugänge nur aus dem eigenen Netz erreichbar machen will, arbeitet mit quellbeschränkten Regeln nach dem Muster ufw allow from 203.0.113.0/24 to any port 22 proto tcp. Noch sauberer ist es, Verwaltungsdienste überhaupt nicht ins offene Netz zu stellen, sondern über ein VPN anzubinden. Eine WireGuard-Instanz ist auf jedem der vier Systeme in wenigen Minuten eingerichtet und ersetzt einen ganzen Stapel Firewall-Ausnahmen durch einen einzigen offenen UDP-Port.

Und zum Schluss die Einordnung, die man sich bewusst machen sollte: UFW filtert auf dem Server selbst. Gegen Volumenangriffe, die die Anbindung sättigen, hilft das prinzipbedingt nicht, denn die Pakete sind bereits über die Leitung gelaufen, wenn Ihr Kernel sie verwirft. Dafür braucht es Filterung im Netz davor. Bei KernelHost übernimmt das die vorgelagerte Infrastruktur im Rechenzentrum maincubes in Frankfurt am Main mit Arbor-Echtzeitfilterung. Ihre lokale Firewall und der Netzschutz lösen zwei verschiedene Probleme, und Sie brauchen beide.

Häufige Fragen

Sperrt mich "ufw enable" sofort aus meiner laufenden SSH-Sitzung aus?
Nein, und genau das ist die Falle. UFW erlaubt in /etc/ufw/before.rules bereits bestehende Verbindungen (Zustand RELATED,ESTABLISHED). Ihre aktuelle Sitzung überlebt das Einschalten also selbst dann, wenn gar keine SSH-Regel existiert. Erst der nächste Verbindungsaufbau scheitert. Prüfen Sie deshalb immer mit einer zweiten, frisch aufgebauten Sitzung, bevor Sie die erste schließen.
Muss ich IPv6 in UFW separat aktivieren?
Auf Debian 13, Debian 12, Ubuntu 24.04 und Ubuntu 22.04 steht IPV6=yes bereits ab Werk in /etc/default/ufw. UFW legt dann zu jeder Regel automatisch eine IPv6-Entsprechung an, erkennbar an der Meldung "Rule added (v6)" und am Zusatz "(v6)" in ufw status. Prüfen können Sie das hart mit ip6tables -L INPUT -n: Dort muss "policy DROP" stehen. Eine Änderung an IPV6 wirkt erst nach ufw disable gefolgt von ufw enable, ein ufw reload genügt nicht.
Nutzt UFW iptables oder nftables?
Beides, in gewissem Sinne. UFW spricht weiterhin iptables-Syntax, aber der Befehl iptables ist auf allen vier Distributionen die Kompatibilitätsschicht iptables-nft. Die Regeln landen also im nftables-Subsystem des Kernels und sind bei aktiver Firewall mit nft list table ip filter sichtbar. Solange UFW noch nicht eingeschaltet ist, existiert diese Tabelle gar nicht und der Befehl meldet "Error: No such file or directory". Prüfen lässt sich das Backend mit iptables -V, die Ausgabe endet mit (nf_tables). Mischen Sie UFW nicht mit handgeschriebenen nft-Regeln: Ein nft flush ruleset löscht alle UFW-Regeln, während ufw status weiterhin "active" meldet.
Was genau macht ufw limit?
ufw limit erlaubt Verbindungen normal, verwirft sie aber, sobald eine einzelne Quell-IP innerhalb von 30 Sekunden sechs oder mehr neue Verbindungen aufbaut. Die Werte sind fest und über die UFW-Oberfläche nicht änderbar. Gegen verteilte Angriffe hilft das nicht, weil pro Quell-IP gezählt wird. Außerdem kann es eigene Automatismen treffen, etwa Backup-Skripte oder CI-Jobs mit vielen parallelen SSH-Verbindungen. Für solche Quellen legen Sie eine explizite Ausnahme davor.
Ich komme nicht mehr per SSH auf den Server. Hilft ein Neustart?
Nein. UFW ist als systemd-Dienst aktiviert und stellt seine Regeln beim Hochfahren wieder her, der Server kommt genauso verschlossen zurück. Nutzen Sie stattdessen die VNC-Konsole im Kundenbereich, melden Sie sich dort als root an und führen Sie ufw disable aus. Danach die Ursache suchen: fehlende SSH-Regel, falscher Port oder eine Quellbeschränkung auf eine IP-Adresse, die Ihr Anschluss nicht mehr hat.
Warum sind meine Docker-Container trotz aktiver UFW-Firewall von außen erreichbar?
Docker legt eigene Ketten an und arbeitet mit Zieladressumsetzung, sodass veröffentlichte Container-Ports an den UFW-Ketten vorbeilaufen. "deny incoming" greift für diesen Verkehr nicht. Die robusteste Lösung ist, Ports nur lokal zu veröffentlichen, also -p 127.0.0.1:8080:80 statt -p 8080:80, und den Zugriff über einen Reverse Proxy zu führen.
Warum existiert /var/log/ufw.log auf meinem Debian-Server nicht?
Weil rsyslog dort nicht installiert ist. Debian 13 liefert in minimalen Installationen keinen Syslog-Daemon mehr aus und verlässt sich auf systemd-journald, Debian 12 je nach Installationsvariante ebenfalls nicht. Die Meldungen sind trotzdem da, Sie lesen sie mit journalctl -k und suchen nach Zeilen mit [UFW BLOCK]. Unter Ubuntu 22.04 und 24.04 ist rsyslog vorhanden, dort existiert die Datei.

UFW Firewall Linux Debian Ubuntu nftables IPv6 SSH Serversicherheit Root Server