ufw Firewall einrichten (2026): Anleitung mit echten Messwerten

ufw Firewall einrichten (2026): Anleitung mit echten Messwerten

Eine ufw Firewall einrichten dauert fünf Minuten: Standardregeln setzen, SSH freigeben, die Ports für den Webserver öffnen, einschalten. Das steht in jeder Anleitung, und es stimmt. Was in fast keiner Anleitung steht, ist, was danach passiert. Wie viel die Firewall tatsächlich abfängt. Ob das Log die Wahrheit zeigt. Ob die Regeln, die man in einem Jahr Betrieb angesammelt hat, überhaupt noch greifen.

Wir haben uns das auf unserem eigenen Produktionsserver angesehen. Der läuft mit Ubuntu 24.04, ufw 0.36.2 und ist seit Monaten im Netz. Ausgewertet haben wir das Kernel-Journal der letzten sieben Tage und die Paketzähler der Firewall, außerdem einen Test von einer fremden Maschine aus.

Drei Befunde vorweg, weil sie den Rest des Artikels bestimmen:

1. In sieben Tagen stehen 34.636 Block-Einträge im Log, von 6.613 verschiedenen Absendern auf 10.442 verschiedene Ports. Das ist nicht alles, was verworfen wurde, sondern nur eine Stichprobe. In einer 15-minütigen Nachmessung hat die Firewall 377 Pakete verworfen und 47 davon protokolliert, also ungefähr jedes achte.

2. Fünf unserer Regeln sind wirkungslos, weil eine Regel weiter oben immer vorher entscheidet. Zwei davon sind Sperren gegen konkrete IP-Adressen. Sie stehen im Regelwerk, ufw status zeigt sie an, und sie tun nichts.

3. Auf Port 22, der offen ist, stehen 2.370 Blocks. Nur 4 davon waren Verbindungsversuche.

Zuerst kommt die Anleitung, danach die Befunde im Detail. Wer nur die Befehle braucht, findet am Ende eine kompakte Checkliste.

Ein Server hinter einer leuchtenden Schutzwand mit drei offenen Toren, an denen rote Partikel abprallen

Was ist ufw überhaupt?

ufw steht für Uncomplicated Firewall. Es ist keine eigene Firewall, sondern eine Bedienoberfläche für den Paketfilter, der ohnehin im Linux-Kernel steckt. Canonical hat ufw für Ubuntu entwickelt; es ist dort vorinstalliert und läuft genauso auf Debian, Linux Mint und den meisten Abkömmlingen.

Der Kernel filtert Pakete mit Netfilter. Die klassischen Befehle, um Netfilter Regeln zu geben, heißen iptables und neuerdings nft (nftables). Beide sind mächtig und unleserlich. Eine einfache Freigabe für HTTPS sieht in iptables so aus:

iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
ip6tables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT

In ufw ist es das hier:

ufw allow 443/tcp

ufw übersetzt das in die entsprechenden Kernel-Regeln, für IPv4 und IPv6 gleichzeitig, und speichert sie so, dass sie einen Neustart überleben. Auf unserem Server ist das Backend übrigens nicht mehr das alte iptables, sondern nftables mit einer Übersetzungsschicht:

$ iptables -V
iptables v1.8.10 (nf_tables)

Für dich als Benutzer ändert das nichts. Die Befehle bleiben dieselben.

Ein einfaches Bedienfeld über einer komplexen Maschine aus Rohren und Ventilen, verbunden durch saubere Kabel

Wofür braucht ein Server überhaupt eine Firewall?

Ein Server, der nur einen Webserver und SSH betreibt, hat theoretisch nur drei offene Ports. In der Praxis lauschen aber viel mehr Programme auf dem Netzwerk, als man denkt. Auf unserem Hauptserver haben wir beim Schreiben gezählt:

ss -tlnH | awk '{print $4}' | grep -v "127.0.0\|\[::1\]"

Ergebnis: 21 TCP-Dienste lauschen auf einer öffentlichen Adresse, 46 weitere nur auf Loopback. Unter den 21 sind Entwicklungsserver von Next.js, Node-Dienste, die auf * statt auf 127.0.0.1 gestartet wurden, und ein Synthesizer-Daemon, von dem niemand mehr weiß, warum er läuft. Ohne Firewall wären alle 21 aus dem Internet erreichbar.

Das ist der eigentliche Zweck einer Host-Firewall: nicht der eine Dienst, den du bewusst öffnest, sondern die fünfzehn, die du versehentlich geöffnet hast. Mehr dazu, wie man Dienste von vornherein richtig bindet, steht in Was ist ein Reverse Proxy.

ufw Firewall einrichten: Schritt für Schritt

Die folgenden Schritte gelten für Ubuntu und Debian. Alle Befehle brauchen Root-Rechte; entweder als root oder mit vorangestelltem sudo.

Schritt 1: Installieren und Status prüfen

Auf Ubuntu ist ufw vorinstalliert, aber nicht aktiv. Auf Debian muss man es meist erst installieren:

apt update && apt install ufw
ufw status

Direkt nach der Installation antwortet ufw mit Status: inactive. Das ist kein Fehler: ufw schaltet sich nie von selbst ein, weil das auf einem entfernten Server sofort die eigene Verbindung kappen könnte.

Schritt 2: Die Standardrichtlinien setzen

Die Grundregel jeder Server-Firewall lautet: Alles Eingehende verbieten, alles Ausgehende erlauben, dann gezielt Ausnahmen öffnen.

ufw default deny incoming
ufw default allow outgoing

“Ausgehend erlauben” heißt: Dein Server darf Updates laden, Mails verschicken, APIs abfragen. “Eingehend verbieten” heißt: Niemand darf von außen eine neue Verbindung zu ihm aufbauen, außer auf den Ports, die du gleich freigibst. Antworten auf Verbindungen, die dein Server selbst geöffnet hat, kommen trotzdem durch. Dafür sorgt die Verbindungsverfolgung des Kernels (conntrack), dazu später mehr.

Es gibt noch eine dritte Richtlinie, routed, für weitergeleiteten Verkehr. Auf einem normalen Server steht sie auf deny und kann so bleiben. Genau hier liegt allerdings die Docker-Falle, die wir weiter unten zeigen.

Schritt 3: SSH freigeben, bevor du irgendetwas einschaltest

Das ist der wichtigste Satz dieser Anleitung. Wenn du ufw auf einem entfernten Server aktivierst, ohne vorher SSH freizugeben, sperrst du dich aus. Die Verbindung, über die du gerade arbeitest, läuft zwar noch weiter, weil sie schon besteht. Die nächste aber nicht mehr.

ufw allow OpenSSH
# oder gleichwertig, wenn SSH auf dem Standardport läuft:
ufw allow 22/tcp comment 'SSH'

OpenSSH ist ein sogenanntes Anwendungsprofil. Pakete, die Netzwerkdienste mitbringen, legen solche Profile unter /etc/ufw/applications.d/ ab. Welche es auf deinem System gibt, zeigt:

ufw app list

Bei uns liefert das unter anderem OpenSSH, Nginx Full, Nginx HTTPS, Postfix und Dovecot Secure IMAP. Der Vorteil von Profilen: Läuft SSH auf einem anderen Port, wird das im Profil gepflegt, und die Regel bleibt richtig.

Wenn du SSH auf einen anderen Port gelegt hast, gib diesen Port frei, nicht 22. Und wenn du von einer festen Adresse aus arbeitest, kannst du SSH auf diese Adresse beschränken:

ufw allow from 203.0.113.5 to any port 22 proto tcp comment 'SSH nur Büro'

Warum SSH-Schlüssel wichtiger sind als jede Firewall-Regel für Port 22, haben wir mit echten Angriffszahlen in Was ist SSH? gezeigt.

Schritt 4: Die Dienste freigeben, die öffentlich sein sollen

Für einen Webserver:

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

Oder über das Profil:

ufw allow 'Nginx Full'

Gib immer das Protokoll mit an. ufw allow 443 ohne /tcp öffnet den Port für TCP und UDP. Das kann gewollt sein, denn HTTP/3 läuft über UDP 443. Auf unserem Server sind über die UDP-443-Regel tatsächlich rund 42.000 Pakete angenommen worden, weil Caddy HTTP/3 spricht. Bei Port 80 dagegen gibt es kein UDP-Protokoll, das irgendjemand braucht, und die Regel ufw allow 80 hat trotzdem 23 UDP-Pakete durchgelassen. Harmlos, weil dort niemand lauscht, aber eben nicht, was gemeint war.

Die Kommentare mit comment '...' sind keine Kosmetik. In einem Jahr weißt du nicht mehr, wofür Port 22005 offen ist. Wir wissen es, weil es dransteht.

Schritt 5: Einschalten

ufw enable

ufw fragt nach, ob du wirklich fortfahren willst, weil bestehende SSH-Verbindungen unterbrochen werden könnten. Wenn Schritt 3 erledigt ist, passiert nichts. Öffne danach ein zweites Terminal und verbinde dich neu, bevor du das erste schließt. Klappt die neue Verbindung, ist alles gut. Klappt sie nicht, kannst du im ersten Fenster noch ufw disable tippen.

ufw ist danach auch nach einem Neustart aktiv. Prüfen lässt sich das mit:

systemctl is-enabled ufw
grep ENABLED /etc/ufw/ufw.conf

Schritt 6: Den Zustand kontrollieren

ufw status verbose

Bei uns sieht der Kopf so aus:

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

Für die Arbeit an einzelnen Regeln ist die nummerierte Ansicht praktischer:

ufw status numbered

Und bevor du eine Änderung wirklich ausführst, kannst du sie dir anzeigen lassen, ohne dass sie greift:

ufw --dry-run allow 8080/tcp

--dry-run gibt die Kernel-Regeln aus, die ufw erzeugen würde. Das ist der schnellste Weg, um zu verstehen, was ein Befehl wirklich tut. Wir haben es für diesen Artikel mehrfach benutzt, um nichts am Produktionsserver zu verändern.

Regeln verwalten: löschen, einfügen, begrenzen

Eine Regel löschen

Es gibt zwei Wege. Über die Nummer:

ufw status numbered
ufw delete 4

Oder über die Regel selbst, indem du delete vor den ursprünglichen Befehl schreibst:

ufw delete allow 80

Der zweite Weg ist sicherer. Nummern verschieben sich nach jedem Löschen, und wer zwei Regeln hintereinander über die Nummer löscht, erwischt beim zweiten Mal die falsche.

Die Reihenfolge entscheidet: die erste passende Regel gewinnt

Das ist das Prinzip, das man bei ufw am häufigsten übersieht, und der Grund für unseren zweiten Befund. ufw prüft Regeln von oben nach unten, und die erste Regel, die passt, entscheidet. Alles darunter wird für dieses Paket nicht mehr angesehen.

Mehrere gestapelte Filterschichten, ein leuchtendes Paket bleibt an der obersten hängen, die unteren bleiben dunkel

Neue Regeln werden mit ufw allow oder ufw deny hinten angehängt. Wer eine IP-Adresse sperren will, die schon Zugriff auf einen offenen Port hat, muss die Sperre deshalb nach vorne setzen:

ufw insert 1 deny from 198.51.100.23 comment 'Scanner'

Ohne insert 1 landet die Sperre unter den Freigaben für 22, 80 und 443. Für diese Ports wird sie nie gefragt.

SSH mit limit gegen schnelle Versuche absichern

Statt allow kennt ufw auch limit. Ein Blick in die erzeugten Regeln zeigt, was dahinter steckt:

$ ufw --dry-run limit 22/tcp
-A ufw-user-input -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --set
-A ufw-user-input -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --update --seconds 30 --hitcount 6 -j ufw-user-limit
-A ufw-user-input -p tcp --dport 22 -j ufw-user-limit-accept

Übersetzt: Wer innerhalb von 30 Sekunden 6 oder mehr neue Verbindungen zu Port 22 aufbaut, wird abgewiesen. Das bremst primitive Brute-Force-Skripte, ersetzt aber kein Werkzeug wie fail2ban. Das zählt fehlgeschlagene Anmeldungen statt Verbindungen und sperrt für Stunden statt für Sekunden. Auf unserem Server hat fail2ban bisher 1.930 Sperren verhängt. Warum auch das weniger bringt als erhofft, haben wir in Linux Server einrichten nachgerechnet.

Vorsicht bei limit, wenn du selbst Automatisierung über SSH betreibst: Deployment-Werkzeuge, die für jeden Schritt eine eigene Verbindung öffnen, erreichen sechs Verbindungen in 30 Sekunden schneller als jeder Angreifer.

IPv6 nicht vergessen

In /etc/default/ufw steht bei aktuellen Installationen IPV6=yes. Dann legt ufw jede Regel doppelt an, einmal für IPv4, einmal für IPv6. Du erkennst das an den Zeilen mit (v6) in ufw status.

Steht dort IPV6=no, filtert ufw nur IPv4. Hat dein Server eine IPv6-Adresse, und fast jeder Cloud-Server hat eine, ist er über IPv6 dann komplett ungefiltert erreichbar. Das ist eine der wenigen Stellen, an denen ufw still das Falsche tun kann. Einmal nachsehen:

grep IPV6 /etc/default/ufw

Zur Einordnung, wie viel über IPv6 ankommt: Auf unserem Server hat die IPv6-Standardrichtlinie seit dem letzten Neustart 24.061 Pakete verworfen. Die IPv4-Richtlinie im selben Zeitraum 4,1 Millionen. IPv6 ist bei Scannern deutlich seltener, weil der Adressraum zu groß ist, um ihn blind abzusuchen. Seltener heißt aber nicht null.

Was die Firewall in einer Woche wirklich abfängt

Jetzt zu dem Teil, der in Anleitungen fehlt. Wir haben die Block-Einträge aus dem Kernel-Journal der letzten sieben Tage gezogen:

journalctl -k --since "7 days ago" --no-pager | grep "UFW BLOCK" > ufwb.txt
wc -l < ufwb.txt

34.636 Einträge. Pro Tag zwischen 4.577 und 6.051, im Schnitt rund 4.900. Die am häufigsten angefragten Ports:

PortBlocksWas dort normalerweise läuft
84434.011alternatives HTTPS, Admin-Oberflächen
222.370SSH (bei uns offen, dazu gleich)
231.748Telnet
33061.631MySQL/MariaDB
30001.177Node-, Grafana-, Entwicklungsserver
8080500HTTP-Proxys, Tomcat
8000364Python-/Django-Entwicklungsserver
4443353alternatives HTTPS
8081341Proxys, Admin-Panels
9000309PHP-FPM, Portainer, MinIO

Die Top 10 machen zusammen nur 12.804 der 34.586 Einträge mit Zielport aus, also gut ein Drittel. Der Rest verteilt sich auf 10.442 verschiedene Zielports. Das ist das Muster eines Massenscans: Irgendjemand klopft systematisch jede Tür ab und schaut, ob irgendwo etwas antwortet.

Die Liste ist ein ziemlich genaues Bild dessen, was Leute versehentlich offen lassen: Datenbanken, Entwicklungsserver auf Port 3000 und 8000, Admin-Panels auf 8443 und 9000, und immer noch Telnet. Genau die Dienste, bei denen “ich teste nur kurz” zu einem Dauerzustand wird. Auf unserem Server lauschen tatsächlich mehrere Node-Dienste im Bereich um 3000 auf allen Adressen. Die Firewall ist der einzige Grund, warum das egal ist.

Das Log ist eine Stichprobe, keine Zählung

Wer diese Zahlen liest, glaubt schnell, das sei alles, was die Firewall abgewehrt hat. Ist es nicht. Ein Blick in die Log-Regel zeigt, warum:

$ iptables -S ufw-after-logging-input
-A ufw-after-logging-input -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "

--limit 3/min --limit-burst 10 heißt: ufw protokolliert im Dauerbetrieb höchstens drei Pakete pro Minute, mit einem Puffer von zehn für kurze Spitzen. Alles darüber wird trotzdem verworfen, aber nicht mehr aufgeschrieben. Das ist sinnvoll, denn ohne Grenze könnte ein einziger Scan die Platte mit Logs füllen. Es heißt aber auch, dass die Logzahl nach oben gedeckelt ist und nichts über das wahre Volumen sagt.

Wir haben nachgemessen, wie groß die Lücke ist. 15 Minuten lang haben wir den Paketzähler der verwerfenden Standardregel mit der Zahl der Logzeilen im selben Zeitraum verglichen:

start=2026-09-29 07:10:47  policy_drops=377  journal=47

377 Pakete verworfen, 47 protokolliert. Das Log zeigt ungefähr jedes achte Paket. Hochgerechnet sind das rund 36.000 verworfene Pakete pro Tag, während im Log täglich knapp 5.000 landen. Die Langzeitzahl passt dazu: Der Zähler der Standardregel steht bei rund 4,1 Millionen IPv4-Paketen, bei 91 Tagen Laufzeit seit dem letzten Neustart etwa 45.000 pro Tag.

Ein großer Strom roter Partikel fließt an einem kleinen Trichter vorbei, der nur ein dünnes Rinnsal in ein Notizbuch leitet

Die Konsequenz für die Praxis: Wenn du wissen willst, wie viel deine Firewall abfängt, lies die Paketzähler, nicht das Log.

iptables -L INPUT -v -n -x | head -1
# Chain INPUT (policy DROP 4102283 packets, 450230683 bytes)

Und wenn eine Auswertung auf dem Log aufbaut, etwa “Port X wird am häufigsten angegriffen”, dann ist das eine Aussage über eine gedrosselte Stichprobe. Die Rangfolge ist grob richtig. Die Absolutzahlen sind es nicht.

Das Protokollieren lässt sich über ufw logging steuern (off, low, medium, high, full). Die Stufe low ist Standard und reicht. Höhere Stufen protokollieren zusätzlich erlaubte Pakete und erzeugen sehr schnell sehr viele Daten.

Port 22 ist offen, und trotzdem 2.370 Blocks?

Der Befund, der uns am meisten überrascht hat: Auf Port 22, den wir ausdrücklich freigegeben haben, stehen 2.370 Block-Einträge. Wie kann eine Firewall etwas blockieren, das sie erlauben soll?

Die Antwort steckt in den TCP-Flags der blockierten Pakete:

grep "DPT=22 " ufwb.txt | grep -o "\(SYN\|ACK\|RST\|FIN\|PSH\)[ A-Z]*URGP" | sort | uniq -c | sort -rn
   2054 ACK PSH URGP
    302 ACK PSH FIN URGP
      9 RST URGP
      4 SYN URGP

Ein neuer Verbindungsversuch beginnt immer mit einem SYN-Paket. Von den 2.370 Blocks waren nur 4 solche Versuche. Die anderen 2.366 waren Datenpakete (ACK PSH) und Abbauversuche (FIN, RST) von Verbindungen, die der Kernel schon nicht mehr kannte.

Das passiert so: Der Kernel merkt sich jede Verbindung in seiner Verbindungstabelle (conntrack). Bricht eine Verbindung ab, weil fail2ban die Gegenseite sperrt, weil ein Timeout abläuft oder weil der Angreifer sein Skript mitten im Handshake killt, verschwindet der Eintrag. Schickt die Gegenseite danach noch Pakete, passen sie zu keiner bekannten Verbindung. Der Kernel stuft sie als INVALID ein, und ufw verwirft INVALID-Pakete ganz am Anfang seiner Regelkette, noch bevor die Portfreigaben überhaupt geprüft werden:

-A ufw-before-input -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-input -m conntrack --ctstate INVALID -j ufw-logging-deny
-A ufw-before-input -m conntrack --ctstate INVALID -j DROP

Das erklärt auch einen zweiten Fund: 81 SYN-Pakete auf Port 443 wurden blockiert, obwohl 443 offen ist. Auf einen offenen Port kann ein Paket in ufw nur über diese INVALID-Regel im Log landen. Alle 81 kamen aus einer Handvoll Adressbereiche mit fast identischen Merkmalen (gleiche Paketlänge, gleiche TCP-Fenstergröße 14600). Das ist das Muster eines Scanners, der seine Pakete selbst bastelt, statt den normalen Netzwerkstapel zu benutzen.

Die Lehre daraus: Ein Block auf einem erlaubten Port heißt nicht, dass die Regel falsch ist. Wer das nicht weiß, fängt an, an funktionierenden Regeln herumzuschrauben. Insgesamt hat die INVALID-Regel bei uns seit dem letzten Laden der Firewall 83.093 Pakete verworfen.

Der hartnäckigste Klopfer war einer von uns

Bei Port 3306 (MySQL) stammten 1.565 der 1.631 Blocks von einer einzigen Adresse. Rund um die Uhr, jede Stunde 20 bis 33 geloggte Versuche, sieben Tage lang. Wir haben die Adresse nachgeschlagen: Es ist ein anderer Server aus unserem eigenen Bestand. Irgendein Dienst dort versucht offenbar noch, eine Datenbankverbindung zu einem Server aufzubauen, der die Datenbank längst nicht mehr nach außen anbietet.

Das ist kein Angriff, sondern eine Altlast, die ohne diese Auswertung nie aufgefallen wäre. Der Dienst auf der anderen Seite bekommt seit Wochen keine Antwort, und niemand hat es gemerkt. Wir haben noch nicht nachverfolgt, welcher Dienst das ist. Das steht jetzt auf unserer Liste.

Deshalb lohnt sich die Auswertung auch dann, wenn man keine Sorge vor Angriffen hat: Eine Firewall sieht auch, was deine eigene Infrastruktur falsch macht. Häufigste Absender herausfinden:

grep -o "SRC=[0-9.]*" ufwb.txt | sort | uniq -c | sort -rn | head

Fünf Regeln, die nichts bewirken

ufw zeigt mit ufw status, welche Regeln existieren. Ob sie jemals etwas tun, zeigt es nicht. Dafür muss man eine Ebene tiefer, in die Paketzähler der Kernel-Regeln:

iptables -L ufw-user-input -v -n -x --line-numbers

Die erste Spalte pkts zählt, wie viele Pakete eine Regel getroffen haben. Bei uns sah das (gekürzt, IP-Adressen durch Beispieladressen ersetzt) so aus:

num    pkts  target  prot  source          destination
1    117923  ACCEPT  tcp   0.0.0.0/0       tcp dpt:22
2    167277  ACCEPT  tcp   0.0.0.0/0       tcp dpt:80
3    251145  ACCEPT  tcp   0.0.0.0/0       tcp dpt:443
4         0  ACCEPT  tcp   0.0.0.0/0       tcp dpt:80
6         0  ACCEPT  tcp   0.0.0.0/0       tcp dpt:443
8         0  ACCEPT  tcp   198.51.100.10   tcp dpt:22
13        0  DROP    all   192.0.2.44
14        0  DROP    all   192.0.2.170

Sieben der 17 Regeln stehen bei null. Zwei davon sind unauffällig: Für sie kam in vier Tagen einfach kein passender Verkehr. Die anderen fünf können nichts bewirken, egal wie viel Verkehr kommt. Sie fallen in drei Gruppen:

Doppelte Freigaben (Zeilen 4 und 6). Irgendwann hat jemand ufw allow 80 eingegeben, obwohl ufw allow 80/tcp schon existierte. ufw akzeptiert das kommentarlos, weil es formal eine andere Regel ist (ohne Protokoll statt mit). Für TCP greift immer die erste. Die zweite wird nie erreicht.

Eine Ausnahme, die schon erlaubt ist (Zeile 8). SSH nur für eine bestimmte Adresse freizugeben ist eine gute Idee. Nur hilft es nichts, wenn weiter oben SSH schon für alle freigegeben ist. Die spezifische Regel ist wirkungslos, und schlimmer: Sie erweckt beim Lesen den Eindruck, SSH sei eingeschränkt.

Sperren, die zu spät kommen (Zeilen 13 und 14). Das sind zwei IP-Sperren, angelegt mit ufw deny from ..., also ohne insert. Sie stehen unter den Freigaben für 22, 80 und 443. Wollte eine dieser Adressen auf die Webseite oder auf SSH zugreifen, würde sie von Zeile 1 bis 3 durchgewunken, bevor die Sperre überhaupt gefragt wird. Auf alle anderen Ports wäre sie ohnehin von der Standardrichtlinie abgewiesen worden. Die Sperre ändert also in keinem einzigen Fall das Ergebnis. Der Zähler bei null sagt dabei nur, dass es keine der beiden Adressen seit dem letzten Laden auf einem anderen Port versucht hat. Hätte sie es getan, wäre die Sperre zwar getroffen worden, aber die Standardrichtlinie hätte ohnehin dasselbe getan.

Das ist die unangenehmste Art Fehler, weil er beruhigt. ufw status listet die Sperre ordentlich auf, mit DENY IN. Wer nachsieht, ob die Adresse gesperrt ist, sieht: ja. Die Zählerspalte sagt etwas anderes.

Die Reparatur ist einfach:

ufw delete deny from 192.0.2.44
ufw insert 1 deny from 192.0.2.44 comment 'gesperrt, Grund: ...'

Und als Gewohnheit: Nach jeder neuen Sperre ein paar Tage später in die Zähler schauen. Eine Sperre mit null Treffern ist entweder überflüssig oder falsch platziert. In beiden Fällen gehört sie überarbeitet.

Wichtig beim Nachmachen: Die Zähler beginnen bei null, wenn ufw neu geladen wird, also nach ufw reload, nach jeder Regeländerung und nach einem Neustart. Bei uns war das letzte Laden vier Tage vor der Messung. Eine Regel mit null Treffern nach vier Tagen Produktionsbetrieb auf Port 80 ist eindeutig. Nach vier Minuten wäre sie es nicht.

Die Docker-Falle: warum ufw manche Container nicht schützt

Diesen Punkt haben wir schon in zwei Artikeln ausführlich gemessen, deshalb hier nur die Zusammenfassung. Wer Docker benutzt, muss ihn trotzdem kennen.

Docker umgeht ufw. Veröffentlicht ein Container einen Port mit der üblichen Schreibweise -p 8080:80 oder in Compose mit "8080:80", ist dieser Port aus dem Internet erreichbar, auch wenn ufw ihn nie freigegeben hat. Docker schreibt eigene Regeln in die FORWARD-Kette des Kernels, und die greifen, bevor ufw gefragt wird. ufw status merkt davon nichts.

Ein fest verschlossenes Haupttor, während eine kleine Seitentür in derselben Mauer offen steht und eine Container-Kiste hindurchgleitet

Wir haben das in Linux Server einrichten mit einem Wegwerf-Container nachgewiesen und im Docker Compose Beispiel für Compose-Dateien noch einmal einzeln gemessen. Beide Male: HTTP 200 von einem fremden Server, obwohl ufw den Port verbietet.

Die Lösung ist, Container-Ports an Loopback zu binden:

ports:
  - "127.0.0.1:8080:80"   # nur lokal, ein Reverse Proxy leitet weiter

Auf unserem Server sind alle Container so gebunden. Zur Kontrolle für diesen Artikel haben wir erneut von einer fremden Maschine in Helsinki aus getestet, einmal einen offenen Port und fünf, die zu sein sollten:

443   OPEN
5050  BLOCKED
9800  BLOCKED
3860  BLOCKED
631   BLOCKED
8443  BLOCKED

Die Ports 5050, 9800 und 3860 gehören zu Diensten, die auf allen Adressen lauschen, also nicht an Loopback gebunden sind. Sie sind trotzdem blockiert, weil es normale Prozesse sind und keine Docker-Container. Genau das ist die Grenze: Für normale Dienste schützt ufw zuverlässig. Für Docker-Container nur, wenn sie richtig gebunden sind.

Teste immer von außen. Ein curl vom Server auf seine eigene öffentliche IP läuft über das Loopback-Interface und durchläuft die Firewall nie. Der Test sagt dann immer “erreichbar” und beweist nichts. Ein zweiter Server, ein Handy im Mobilfunknetz oder ein Online-Portscanner reichen.

ufw vs. iptables vs. nftables vs. firewalld

Eine häufige Frage ist, ob man überhaupt ufw nehmen sollte oder gleich etwas “Richtiges”.

ufwiptables / nftables direktfirewalld
ZielgruppeEinzelserver, Einsteiger bis ProfiSpezialfälle, Router, komplexe SetupsRed Hat, Fedora, CentOS, Rocky
Syntaxufw allow 443/tcplange RegelkettenZonen und Dienste
IPv4 + IPv6automatisch beidesgetrennt pflegen (iptables) bzw. inet (nftables)automatisch beides
Persistenzeingebautselbst kümmerneingebaut
VorinstalliertUbuntuüberall (als Kernel-Werkzeug)RHEL-Familie

ufw ist keine Einsteiger-Firewall, die man später durch etwas Besseres ersetzt. Die Regeln, die ufw erzeugt, sind dieselben Kernel-Regeln, die du auch von Hand schreiben würdest. Für einen einzelnen Server mit ein paar öffentlichen Diensten gibt es keinen technischen Grund, auf direkte iptables-Regeln umzusteigen. Wer mehr braucht, kann in /etc/ufw/before.rules eigene Regeln ergänzen, ohne ufw aufzugeben.

Mische nicht mehrere Firewall-Werkzeuge. Wer ufw benutzt und zusätzlich per Hand iptables-Regeln setzt, hat zwei Stellen, an denen Regeln entstehen, und nur eine davon zeigt ufw status. Auf Fedora und RHEL-Systemen ist firewalld vorinstalliert. Dort ufw nachzuinstallieren ist möglich, aber nicht sinnvoll. Welche Distribution für einen Server passt, haben wir in Linux Server Distributionen verglichen.

Eine Ausnahme gibt es bei uns selbst: fail2ban schreibt seine Sperren nicht über ufw, sondern direkt in eine eigene nftables-Tabelle (inet f2b-table). Das ist bewusst so und funktioniert, weil fail2ban seine Regeln selbst verwaltet. Man muss es aber wissen, sonst sucht man gesperrte Adressen in ufw status vergeblich.

Reicht ufw als Schutz für einen Server?

Nein. ufw erledigt genau eine Aufgabe: Es entscheidet, welche Ports von außen erreichbar sind. Das ist wichtig, und ohne diese Aufgabe wären bei uns 21 Dienste statt drei öffentlich. Aber auf den Ports, die offen sind, schützt ufw nichts. Wer SSH mit Passwort betreibt, ist trotz Firewall angreifbar. Wer eine veraltete Webanwendung auf Port 443 laufen lässt, auch.

Eine Firewall ist die äußere Schicht. Dahinter braucht es:

  • SSH nur mit Schlüsseln, Root-Login mit Passwort aus (Was ist SSH?)
  • automatische Sicherheitsupdates, die auch wirklich wirksam werden (dazu unser Befund in Linux Server einrichten)
  • Dienste an Loopback binden und nur über einen Reverse Proxy öffentlich machen (nginx als Reverse Proxy)
  • Backups, die schon einmal zurückgespielt wurden

Und bei gemieteten Servern gibt es oft zusätzlich eine Firewall beim Anbieter, die vor dem Server greift. Hetzner, Netcup und die meisten Cloud-Anbieter bieten sie kostenlos an. Sie ersetzt ufw nicht, ergänzt es aber gut: Was dort schon verworfen wird, erreicht den Server gar nicht erst. Was ein VPS überhaupt ist und wie er sich von einem dedizierten Server unterscheidet, steht in Was ist ein VPS?.

Checkliste: ufw Firewall einrichten

In der Reihenfolge, in der wir es machen würden:

# 1. Installieren (Debian) bzw. prüfen (Ubuntu)
apt install ufw
grep IPV6 /etc/default/ufw          # muss "yes" sein

# 2. Standardrichtlinien
ufw default deny incoming
ufw default allow outgoing

# 3. SSH ZUERST
ufw allow OpenSSH                    # oder: ufw limit 22/tcp comment 'SSH'

# 4. Öffentliche Dienste, immer mit Protokoll und Kommentar
ufw allow 80/tcp comment 'HTTP'
ufw allow 443/tcp comment 'HTTPS'
ufw allow 443/udp comment 'HTTP/3'  # nur wenn dein Webserver HTTP/3 spricht

# 5. Einschalten, in einem ZWEITEN Terminal neu verbinden
ufw enable

# 6. Kontrolle
ufw status verbose

Danach, als regelmäßige Pflege:

  • Von außen testen, nie vom Server selbst.
  • Sperren immer mit insert 1 anlegen, sonst stehen sie hinter den Freigaben.
  • Paketzähler lesen, nicht nur ufw status: iptables -L ufw-user-input -v -n -x. Regeln mit null Treffern prüfen.
  • Docker-Ports an 127.0.0.1 binden. ufw sieht sie sonst nicht.
  • Das Log als Stichprobe lesen. Für Mengen die Zähler nehmen.

Was wir nicht gemessen haben

Damit die Zahlen richtig eingeordnet werden:

  • Ein Server, eine Woche. Die Verteilung der angegriffenen Ports hängt vom Netz des Anbieters, von der IP-Historie und vom Zufall ab. Bei einem anderen Server sieht die Top 10 anders aus. Das Muster (tausende Ports, Datenbanken und Entwicklungsserver weit oben) findet sich aber überall wieder.
  • Das Verhältnis „jedes achte Paket“ stammt aus 15 Minuten Messung am Morgen und passt grob zur Langzeitzahl (dort eher jedes neunte, sofern der Richtlinienzähler seit dem Neustart ungestört durchläuft; das haben wir nicht separat geprüft). In Phasen mit starkem Scan-Verkehr ist die Lücke größer, weil die Log-Grenze von drei pro Minute fest ist und der Verkehr nicht.
  • Die Paketzähler der einzelnen Regeln laufen erst seit dem letzten Laden der Firewall, bei uns vier Tage. Für Port 80 und 443 ist das eindeutig, für selten genutzte Ports wie eine Spiele-Freigabe wäre es das nicht.
  • Wir haben nichts an der Firewall verändert, auch die toten Regeln nicht. Alle Befehle, die etwas geändert hätten, liefen mit --dry-run. Aufgeräumt wird separat und bewusst, nicht nebenbei beim Schreiben eines Artikels.

Häufige Fragen

Wie richte ich eine ufw Firewall ein?

Installieren (apt install ufw, auf Ubuntu schon vorhanden), dann ufw default deny incoming und ufw default allow outgoing setzen, zuerst SSH freigeben (ufw allow OpenSSH), danach die öffentlichen Dienste wie ufw allow 80/tcp und ufw allow 443/tcp, und schließlich ufw enable. Anschließend in einem zweiten Terminal neu verbinden, um sicherzugehen, dass SSH noch funktioniert.

Ist ufw auf Ubuntu standardmäßig aktiv?

Nein. ufw ist auf Ubuntu vorinstalliert, aber inaktiv. ufw status zeigt direkt nach der Installation Status: inactive. Das ist Absicht: Eine Firewall, die sich von selbst einschaltet, könnte auf einem entfernten Server die SSH-Verbindung kappen.

Wie gebe ich einen Port in ufw frei?

Mit ufw allow PORT/PROTOKOLL, zum Beispiel ufw allow 8080/tcp. Gib das Protokoll immer mit an; ohne /tcp oder /udp öffnet ufw beides. Für eine Freigabe nur für eine bestimmte Adresse: ufw allow from 203.0.113.5 to any port 8080 proto tcp.

Wie lösche ich eine ufw-Regel?

Entweder mit ufw status numbered die Nummer ermitteln und ufw delete NUMMER ausführen, oder den ursprünglichen Befehl mit delete davor wiederholen, etwa ufw delete allow 8080/tcp. Der zweite Weg ist sicherer, weil sich Nummern nach jedem Löschen verschieben.

Warum greift meine ufw-Sperre gegen eine IP-Adresse nicht?

Weil ufw die erste passende Regel anwendet und ufw deny die Sperre hinten anhängt. Steht davor eine Freigabe für Port 80 oder 443, wird die Adresse dort durchgelassen, bevor die Sperre gefragt wird. Sperren deshalb mit ufw insert 1 deny from ADRESSE an den Anfang setzen. Ob eine Regel greift, zeigt iptables -L ufw-user-input -v -n -x in der Spalte pkts.

Schützt ufw auch Docker-Container?

Nicht bei der Standardkonfiguration. Container-Ports, die mit -p 8080:80 veröffentlicht werden, sind aus dem Internet erreichbar, auch wenn ufw sie nicht freigibt. Docker setzt seine Regeln vor die von ufw. Die Lösung: Ports an Loopback binden (127.0.0.1:8080:80) und einen Reverse Proxy davorstellen.

Warum zeigt das ufw-Log Blocks auf Ports, die offen sind?

Weil ufw Pakete verwirft, die zu keiner bekannten Verbindung gehören (Zustand INVALID), und zwar bevor es die Portfreigaben prüft. Das sind meist Nachzügler von abgebrochenen oder gesperrten Verbindungen. Bei uns waren von 2.370 Blocks auf dem offenen SSH-Port nur 4 echte Verbindungsversuche.

Zeigt das ufw-Log alle blockierten Pakete?

Nein. Die Standard-Logstufe low protokolliert höchstens etwa drei Pakete pro Minute, mit kurzem Puffer für Spitzen. In unserer Messung wurde ungefähr jedes achte verworfene Paket protokolliert. Für echte Mengen die Paketzähler lesen: iptables -L INPUT -v -n -x.

Brauche ich ufw, wenn mein Anbieter eine Firewall hat?

Es schadet nicht, beides zu haben, und es hilft oft. Die Anbieter-Firewall hält Verkehr vom Server fern, ist aber an eine Weboberfläche gebunden und zieht nicht mit, wenn du den Server umziehst. ufw liegt auf dem Server selbst und schützt auch dann, wenn jemand die Anbieter-Regeln versehentlich lockert. Beide zusammen sind robuster als jede allein.

Was ist der Unterschied zwischen ufw und firewalld?

Beide sind Oberflächen für denselben Kernel-Paketfilter. ufw ist auf Ubuntu und Debian zu Hause und arbeitet mit einfachen Regeln pro Port. firewalld ist auf Fedora, RHEL und deren Abkömmlingen Standard und arbeitet mit Zonen, denen man Netzwerkschnittstellen zuordnet. Nimm das, was deine Distribution mitbringt, und mische nicht beide.

Fazit

Eine ufw Firewall einzurichten ist wirklich einfach, und das ist ihr größter Vorteil. Sechs Befehle, und statt 21 Diensten sind drei aus dem Internet erreichbar. Allein das rechtfertigt ufw auf jedem Server.

Die Arbeit fängt aber danach an. Unsere Firewall hat in einer Woche Zehntausende Pakete abgewiesen, und trotzdem standen im selben Regelwerk zwei IP-Sperren, die nie etwas gesperrt haben. ufw status zeigt, was du konfiguriert hast. Die Paketzähler zeigen, was davon tatsächlich passiert. Wer sich nur auf das Erste verlässt, sieht eine ordentliche Liste und hält sie für eine funktionierende Firewall.

Ein Blick pro Monat in iptables -L ufw-user-input -v -n -x reicht, um das zu merken. Diesen Blick sparen sich fast alle, auch wir, bis wir diesen Artikel geschrieben haben.