Host-Firewalls auf Linux-Servern werden zunehmend behandelt wie Anwendungscode: Die Regeln liegen in einem Repository, Änderungen laufen über ein Review, ein Werkzeug rollt sie aus. Das ist richtig – und es stellt beim Umstieg eine Falle, die leicht zu übersehen ist. Am Ende steht ein Server, der sich völlig normal verhält und trotzdem nichts mehr filtert.
Dieser Beitrag erklärt den Mechanismus am Beispiel von nftables, dem Paketfilter-Framework heutiger Linux-Distributionen, beschreibt eine sichere Reihenfolge für die Migration und ergänzt zwei weitere Stolperstellen: Regeln, die aus offenen Sockets abgeleitet werden, und Container-Ports, die an der Host-Firewall vorbeilaufen.
Wie der Distributionsdienst arbeitet
Debian liefert mit dem Paket nftables einen systemd-Dienst nftables.service aus. Seine Unit-Datei ist kurz und eindeutig: Beim Start und beim Reload lädt er die Datei /etc/nftables.conf mit nft -f. Beim Stopp führt er nft flush ruleset aus.
Hinzu kommt die mitgelieferte Konfigurationsdatei, deren erste Anweisung flush ruleset ist. Das nftables-Wiki beschreibt, was dieser Befehl tut: Er löscht den kompletten Regelsatz – „flush (erase, delete, wipe) the complete ruleset“. Gemeint sind nicht nur die Tabellen, die dieser Dienst angelegt hat, sondern alles, was im Kernel geladen ist.
Für einen Server, auf dem nur dieser Dienst Regeln verwaltet, ist das ein sinnvolles Design: Der Regelsatz wird bei jedem Laden vollständig ersetzt, Reste früherer Stände bleiben nicht zurück.
Die Falle beim Wechsel des Mechanismus
Problematisch wird es, sobald ein zweiter Mechanismus hinzukommt. Ein typischer Hergang: Die Regeln sollen künftig aus einem Repository kommen und über ein Konfigurationsmanagement oder einen eigenen Dienst geladen werden, in einer eigenen Tabelle. Der neue Regelsatz wird geladen, geprüft und für gut befunden. Der alte Dienst bleibt stehen, weil er ja nicht stört.
Irgendwann danach passiert eines von drei Dingen:
- Jemand stoppt den alten Dienst, etwa beim Aufräumen. Der Stopp leert den gesamten Regelsatz – einschließlich der neuen Tabelle. Der Host ist danach ungefiltert.
- Jemand startet ihn neu oder lädt ihn neu. Die alte Datei wird eingespielt, ihr
flush rulesetentfernt alles, was nicht in ihr steht. Der Host läuft wieder mit dem Stand, den man abgelöst hatte. - Jemand spielt die alte Datei von Hand ein, um „kurz etwas zu testen“ – mit demselben Ergebnis.
In keinem der Fälle gibt es eine Fehlermeldung. Dienste bleiben erreichbar, Anwendungen funktionieren, das Monitoring bleibt grün. Genau das macht die Falle gefährlich: Die üblichen Tests nach einer Änderung prüfen, ob etwas funktioniert – nicht, ob etwas blockiert wird.
Die sichere Reihenfolge
Die Lösung ist keine neue Technik, sondern eine Reihenfolge:
- Den alten Dienst deaktivieren oder maskieren, ohne ihn zu stoppen. Die systemctl-Handbuchseite ist hier eindeutig:
disablestoppt die Unit nicht; erst die Option--nowtut das.maskgeht weiter und macht jedes Starten unmöglich, auch das manuelle. Einstopwäre genau der Befehl, der den Regelsatz leert. - Den neuen Regelsatz laden – in einer eigenen Tabelle, aus dem Repository, über den Mechanismus, der ihn künftig verwaltet.
- Lesen, was tatsächlich geladen ist.
nft list tableszeigt, welche Tabellen existieren;nft list rulesetzeigt den vollständigen Stand. In dieser Phase sollten alte und neue Tabelle nebeneinander stehen. Beide greifen gleichzeitig – halten Sie diese Phase kurz. - Die Filterung von außen belegen – dazu gleich mehr.
- Erst dann die alte Tabelle gezielt entfernen, mit
nft delete table, nicht über einen Stopp des alten Dienstes. Die alte Konfigurationsdatei wird archiviert oder so geändert, dass ein versehentliches Einspielen nichts mehr leert. - Nach dem nächsten Neustart erneut lesen, ob der neue Regelsatz geladen ist und der alte nicht zurückkehrt.
Ein Detail verdient Aufmerksamkeit: Deaktivieren und Maskieren verhindern ein erneutes Starten, sie beenden den laufenden Zustand aber nicht. Weil die Unit als einmaliger Dienst mit RemainAfterExit=yes angelegt ist, steht sie für systemd bis zum nächsten Neustart weiter als aktiv da – und ihr Stopp-Befehl bleibt hinterlegt. Dokumentieren Sie das als bekanntes Risiko.
Die Negativprobe von außen
Nach jeder Firewall-Änderung wird geprüft, ob erlaubte Dienste erreichbar sind. Das belegt, dass nichts kaputt ist. Dass gefiltert wird, belegt es nicht – ein Host ganz ohne Regeln besteht diesen Test ebenso.
Deshalb gehört zu jeder Änderung eine Negativprobe: ein Verbindungsversuch von einer Quelle außerhalb des Hosts, die blockiert werden muss, auf einen Port, der gesperrt sein muss. Erst wenn dieser Versuch scheitert, ist die Wirkung belegt. „Außerhalb“ ist wörtlich zu nehmen: Verbindungen, die ein Host zu sich selbst aufbaut, laufen über die Loopback-Schnittstelle, die Regelsätze üblicherweise pauschal erlauben.
Wiederholen Sie die Probe regelmäßig, nicht nur bei Änderungen: Die beschriebene Falle kann erst Wochen später zuschnappen.
Regeln aus dem Repository, nicht aus der Shell
Ad-hoc-Befehle auf der Konsole sind der natürliche Gegenspieler jeder Regelverwaltung als Code. Eine Regel, die nur im laufenden Kernel existiert, verschwindet beim nächsten Laden aus dem Repository – oder sie überlebt dort, wo niemand sie erwartet, weil jemand den laufenden Stand in eine Datei exportiert. Beides macht den Regelsatz unberechenbar. Die Regel ist einfach: Was nicht im geprüften Repository steht, gehört nicht auf den Host. Notfalländerungen werden nachgezogen, und ein regelmäßiger Abgleich zwischen Repository und nft list ruleset macht Abweichungen sichtbar.
Nicht jeder offene Socket braucht eine Regel
Beim Aufbau eines neuen Regelsatzes liegt es nahe, die Liste der offenen Sockets eines Hosts abzuarbeiten und für jeden eine Freigabe anzulegen. Das führt zu überflüssigen Öffnungen. Ein Beispiel ist ein UDP-Socket, den ein Protokolldienst nur zum Versenden nutzt, etwa beim Weiterleiten von Syslog-Meldungen an einen zentralen Server. Er taucht in der Socket-Liste auf, braucht aber keine eingehende Regel.
Leiten Sie Freigaben aus dem Zweck ab: Welche Verbindungen soll der Host von wem annehmen? Die Socket-Liste ist ein Werkzeug zur Kontrolle, nicht die Vorlage.
Container-Ports laufen an INPUT vorbei
Die dritte Stolperstelle betrifft Hosts mit Docker. Nach der Docker-Dokumentation werden veröffentlichte Ports standardmäßig an alle Adressen des Hosts gebunden; das Veröffentlichen sei „insecure by default“. Die Pakete durchlaufen eine Destination-NAT-Umleitung und werden in der FORWARD-Kette an Docker-eigene Ketten weitergereicht. Für UFW formuliert die Dokumentation die Konsequenz ausdrücklich: Docker leitet Container-Verkehr in der nat-Tabelle um, bevor er die INPUT- und OUTPUT-Ketten erreicht, die UFW verwendet. Eine sorgfältig gepflegte INPUT-Regel sieht einen veröffentlichten Container-Port also nicht.
Soll ein Dienst im Container nur lokal erreichbar sein, binden Sie ihn ausdrücklich an 127.0.0.1, etwa mit -p 127.0.0.1:8080:80. Dann kann laut Dokumentation nur der Host selbst zugreifen – mit einer Einschränkung: Vor Docker 28.0.0 konnten Hosts im selben Layer-2-Segment auch an localhost veröffentlichte Ports erreichen. Für Filterregeln, die auch vor Containern greifen sollen, gilt: Beim standardmäßigen iptables-Backend sieht Docker dafür die Kette DOCKER-USER vor; mit dem experimentellen nftables-Backend entfällt sie. Veröffentlichte Container-Ports gehören außerdem in jede Negativprobe.
Wie sector7 unterstützt
Wir härten Betriebssysteme und Standard-Services und bauen mit Ihnen saubere, nachvollziehbare Regelwerke auf – mehr unter Cyber Security. Wiederkehrende, automatisierte Schwachstellen-Scans prüfen extern Ihre Angriffsfläche und intern Systeme und Dienste; sie zeigen, wenn ein Port offen ist, der es nicht sein sollte. Im Rahmen unserer Managed Network Services übernehmen wir auch das Change-Management.
Quellen
- nftables.service (Debian-Paketquelle) – Debian pkg-netfilter-team, abgerufen 30.09.2026
- nftables.conf (Debian-Paketquelle) – Debian pkg-netfilter-team, abgerufen 30.09.2026
- Operations at ruleset level – nftables-Wiki, abgerufen 30.09.2026
- Configuring tables – nftables-Wiki, abgerufen 30.09.2026
- systemctl(1), Debian Bookworm – Debian, abgerufen 30.09.2026
- Packet filtering and firewalls – Docker, abgerufen 30.09.2026
- Port publishing and mapping – Docker, abgerufen 30.09.2026
- Docker with iptables – Docker, abgerufen 30.09.2026
- Docker with nftables – Docker, abgerufen 01.10.2026