nftables¶Erinnerung – „Datenpaket“: Daten werden im Netz nicht am Stück übertragen, sondern in kleine Stücke zerlegt. Jedes Stück – ein Datenpaket – bekommt einen Kopf (Header) mit Zusatzinfos wie Quell-/Ziel-IP und Port (vgl. Netzwerk-Grundlagen).
Eine Firewall ist ein Filter zwischen Netzen (oder direkt vor einem einzelnen Rechner): Sie entscheidet anhand von Regeln, welche Datenpakete durchgelassen und welche blockiert werden.
Dieses Kapitel baut direkt auf den Netzwerk-Grundlagen auf. Falls Begriffe wie Port, IP-Adresse, TCP/UDP, CIDR (/16) oder NAT unklar sind, lohnt ein Blick zurück in Computernetze - Einführung.
Lernziele. Nach diesem Kapitel solltest du
- erklären können, was eine Firewall tut und wonach sie filtert (IP, Port, Protokoll, Richtung);
- das Prinzip Default-Deny (Whitelist) verstehen;
- den Unterschied zwischen stateless und stateful Filtern kennen;
- Host- von Netz-Firewalls unterscheiden;
- eine einfache
nftables-Regel lesen können - am Beispiel des IaC-Belegs.
Kurz erklärt – was ist ein Port? Eine IP-Adresse benennt den Rechner im Netz; ein Port (eine Zahl von 0 bis 65535) benennt den Dienst auf diesem Rechner. So können auf einer IP viele Dienste gleichzeitig laufen, jeder auf seinem eigenen Port. Ein Datenpaket trägt darum neben der Ziel-IP auch einen Ziel-Port, der angibt, welcher Dienst gemeint ist.
Sobald ein Rechner Dienste im Netz anbietet, ist er über seine Ports erreichbar (z. B. Port 80/443 für einen Webserver, 22 für SSH). Aus den Netzwerk-Grundlagen wissen wir: Ein Datenpaket trägt u. a. eine Ziel-IP und einen Ziel-Port.
Das Problem: Standardmäßig kann jeder aus dem Internet versuchen, jeden offenen Port zu erreichen. Läuft auf dem Server z. B. eine Datenbank oder ein Admin-Zugang, soll dieser aber keinesfalls für die ganze Welt offen sein.
Erinnerung – „Verbindung“: Zwei Rechner, die über TCP kommunizieren, bauen dafür zuerst eine Verbindung auf (Connection-Request / -Reply), tauschen dann Daten aus und beenden sie wieder – siehe Netzwerk-Grundlagen.
Eine Firewall schränkt das gezielt ein: Sie lässt nur die gewollten Verbindungen zu und blockiert den Rest - noch bevor das Paket die eigentliche Anwendung erreicht.
Eine Firewall ist ein Paketfilter. Für jedes Datenpaket, das sie passieren will, prüft sie eine Liste von Regeln und trifft eine Entscheidung:
Die Regeln werden der Reihe nach geprüft; die erste passende Regel entscheidet. Passt keine Regel, greift die Default-Policy (siehe unten).
Eine Firewall trifft ihre Entscheidung anhand der Metadaten eines Pakets - also genau der Felder, die wir aus dem Schichtenmodell kennen:
| Kriterium | Schicht | Beispiel |
|---|---|---|
| Quell-/Ziel-IP-Adresse | Internetschicht (IP) | nur Pakete aus 141.45.0.0/16 |
| Protokoll | Transportschicht | TCP oder UDP |
| Quell-/Ziel-Port | Transportschicht | Ziel-Port 8080 (Webserver) |
| Richtung | - | eingehend (input) vs. ausgehend (output) |
So lässt sich z. B. die Regel formulieren: "Erlaube eingehende TCP-Pakete mit Ziel-Port 8080, aber nur, wenn die Quell-IP aus dem HTW-Netz stammt."
Hinweis: Ein klassischer Paketfilter schaut nur auf diese Kopf-Informationen (Header), nicht in den Inhalt der Pakete. Firewalls, die auch den Anwendungsinhalt prüfen (z. B. HTTP-Inhalte), nennt man Application-Level-Firewalls bzw. Proxies - das ist hier nicht das Thema.
Passt auf ein Paket keine einzige Regel, muss die Firewall trotzdem entscheiden. Das regelt die Default-Policy. Es gibt zwei grundsätzliche Strategien:
Merksatz - Default-Deny: Sichere Firewalls arbeiten nach dem Whitelist-Prinzip: erst alles blockieren, dann gezielt einzelne Dinge freischalten. Das ist das Standard-Vorgehen und auch die Idee hinter dem Beleg-Beispiel weiter unten.
Wenn ein Rechner eine Webseite abruft, baut er (per TCP, vgl. Netzwerk-Grundlagen) eine Verbindung zum Server auf und erwartet eine Antwort. Eine Firewall muss diese Antwort wieder hereinlassen - sonst käme nie eine Webseite an.
established, related), ohne dass man dafür eine eigene Öffnungsregel braucht.Moderne Firewalls (auch nftables) arbeiten in der Regel stateful. Das macht die Regelwerke kürzer und sicherer.
Aus den Netzwerk-Grundlagen kennen wir bereits einen solchen Übergangspunkt: den Router / das Gateway, das per NAT das lokale Netz mit dem Internet verbindet. Häufig ist die Firewall genau dort angesiedelt. NAT selbst wirkt schon wie ein einfacher Schutz: Rechner mit privaten IPs (10.x, 192.168.x, ...) sind von außen nicht direkt erreichbar.
Die eigentliche Filterung steckt im Linux-Kernel - im Subsystem netfilter. Die bekannten Kommandozeilen-Werkzeuge konfigurieren nur die Regeln; filtern tut der Kernel selbst.
| Werkzeug | Rolle |
|---|---|
nftables (Befehl /usr/sbin/nft) |
aktueller Standard, löst iptables ab - wir verwenden es hier |
iptables |
klassisches, älteres Werkzeug; sehr verbreitet, wird aber abgelöst |
ufw |
Uncomplicated Firewall: einfaches Frontend, das im Hintergrund Regeln erzeugt |
Im Folgenden betrachten wir nftables.
Im Beleg läuft auf einer VM ein Web-Analytics-Stack. Zwei Ports sollen von außen erreichbar sein:
8080 - die Webseite (Nginx),3000 - das Analyse-Werkzeug Umami.Aber: erreichbar nur aus den HTW-Netzen, nicht aus dem ganzen Internet. In der nftables-Konfiguration (/etc/nftables.conf) steht dafür im chain input-Block die Regel:
ip saddr { 10.4.0.0/16, 141.45.0.0/16 } tcp dport { 3000, 8080 } counter accept
Stück für Stück gelesen:
| Teil | Bedeutung |
|---|---|
ip saddr { ... } |
Quell-IP-Adresse (source address) muss in einem der Bereiche liegen |
10.4.0.0/16, 141.45.0.0/16 |
zwei Netze in CIDR-Notation - die HTW-Adressbereiche |
tcp dport { 3000, 8080 } |
Ziel-Port (destination port) ist 3000 oder 8080, Protokoll TCP |
counter |
zählt mit, wie viele Pakete die Regel treffen (nur Statistik) |
accept |
passende Pakete werden durchgelassen |
Damit greifen alle vier Filterkriterien von oben zusammen: Quell-IP (saddr), Protokoll (tcp), Ziel-Port (dport) und - durch die input-Chain - die Richtung (eingehend).
Entscheidend ist das Zusammenspiel mit der Default-Policy: Die
input-Chain blockiert standardmäßig alles (Default-Deny). Diese eine Regel öffnet gezielt nur die beiden Ports und nur für die HTW-Netze. Ein Zugriff aus einem anderen Netz passt nicht auf die Regel und wird daher verworfen.
Das Anzeigen der aktiven Regeln ist ungefährlich (es verändert nichts). Das Setzen von Regeln erfordert dagegen Root-Rechte und kann - falsch gemacht - den eigenen (SSH-)Zugang aussperren. Daher hier nur lesende Befehle; Änderungen zeigen wir als Code-Schnipsel, ohne sie auszuführen.
# Aktuelles nftables-Regelwerk anzeigen (benötigt i. d. R. root, also 'sudo')
/usr/sbin/nft list ruleset 2>/dev/null || echo "nftables nicht verfügbar oder keine Rechte (mit 'sudo' erneut versuchen)"
# Fallback: klassisches iptables, nur anzeigen (-L), numerisch (-n) - nicht ausgeführt:
# sudo iptables -L -n
Im Beleg müssen Sie die Firewall so anpassen, dass die beiden Ports der Anwendung von den HTW-Netzen aus erreichbar sind. Die Regeln liegen in der Datei /etc/nftables.conf und werden als root bearbeitet (dieser Schritt ist bei uns kein IaC, sondern manuelle Server-Administration).
⚠️ Vorsicht – du kannst dich aussperren! Eine falsche Firewall-Regel kann dir den Zugang zur VM nehmen:
- Blockierst du versehentlich Port
22(SSH) oder setzt eine Default-Deny-Policy ohne eine Regel, die SSH erlaubt, ist die VM per SSH nicht mehr erreichbar.- Ein Syntaxfehler in
/etc/nftables.confkann verhindern, dass das gesamte Regelwerk korrekt lädt.So gehst du auf Nummer sicher:
- Lass deine aktuelle SSH-Sitzung geöffnet, während du testest – schließe sie erst, wenn der Zugang in einer zweiten Sitzung bestätigt ist.
- Stelle sicher, dass eine Erlaubnis-Regel für SSH (Port
22) vorhanden ist und bleibt.- Teste das Regelwerk zuerst (siehe unten), bevor du es dauerhaft machst.
Konkret für den Beleg: Öffne /etc/nftables.conf als root und ergänze im Block chain input die Regel aus dem Beispiel oben:
sudo nano /etc/nftables.conf # oder ein anderer Editor
Im chain input-Block einfügen:
ip saddr { 10.4.0.0/16, 141.45.0.0/16 } tcp dport { 3000, 8080 } counter accept
Damit werden die Ports 3000 (Umami) und 8080 (Nginx) genau für die HTW-Netze freigegeben – alle anderen eingehenden Zugriffe auf diese Ports bleiben durch die Default-Deny-Policy blockiert.
Hinweis – Ports kommen aus der
.env:3000und8080sind die Default-Werte des Belegs. Im Projekt stehen sie alsUMAMI_PORT/WEB_PORTindeploy/.envund werden von dort incompose.yamlundhtml/index.htmleingesetzt (Single Source of Truth). Da nftables die.envnicht selbst liest, kannst du die passende Regel-Zeile einmalig daraus erzeugen, damit sie zu deinen Ports passt:source /home/local/iac/.env # liefert WEB_PORT / UMAMI_PORT echo "ip saddr { 10.4.0.0/16, 141.45.0.0/16 } tcp dport { $UMAMI_PORT, $WEB_PORT } counter accept"Die ausgegebene Zeile fügst du dann in
/etc/nftables.confein. (Vgl.README.md, Abschnitt „Firewall".)
Nach dem Bearbeiten muss das Regelwerk neu geladen werden. Erst testen, dann dauerhaft aktivieren:
Als root:
# 1. Syntaxprüfung + sofort laden (zeigt Fehler an, ohne Reboot):
/usr/sbin/nft -f /etc/nftables.conf
# 2. Prüfen, ob die Regel aktiv ist:
/usr/sbin/nft list ruleset
# 3. Dauerhaft (über Reboots) aktivieren bzw. neu laden:
systemctl enable nftables # beim Booten automatisch laden
systemctl restart nftables # Regelwerk aus /etc/nftables.conf neu laden
Anschließend von einem Rechner im HTW-Netz (ggf. über VPN) prüfen, ob die Anwendung erreichbar ist:
curl http://<VM-IP>:8080 # Nginx-Webseite
curl http://<VM-IP>:3000 # Umami
Tipp – mehrere Deployments auf einem Server: Laufen mehrere Stacks mit unterschiedlichen Host-Ports, müssen die zusätzlichen Ports in die Regel aufgenommen werden, z. B.
tcp dport { 3000, 8080, 3001, 8081 }.
Aufgabe 1 (Wiederholung CIDR).
Die Regel oben erlaubt Zugriffe aus 141.45.0.0/16. Liegt die IP 141.45.200.17 in diesem Netz? Und 141.46.0.3? (Tipp: bei /16 müssen nur die ersten 16 Bit - also die ersten zwei Bytes - übereinstimmen.)
Aufgabe 2 (Default-Policy).
Warum ist es sicherer, die input-Chain auf Default-Deny zu stellen und einzelne Ports freizugeben, als alles zu erlauben und nur einzelne Ports zu sperren?
Aufgabe 3 (stateful). Der Server darf selbst Pakete ins Internet senden (z. B. um Updates zu laden) und Antworten empfangen. Warum braucht man dank einer stateful Firewall dafür keine eigene Regel, die alle möglichen Antwort-Ports öffnet?
Aufgabe 4 (optional).
Sieh dir mit /usr/sbin/nft list ruleset (bzw. sudo iptables -L -n) das Regelwerk deines eigenen Rechners an. Welche Ketten (chains) gibt es, und was ist deren Default-Policy?
Aufgabe 5 (Beleg).
Ergänze in /etc/nftables.conf die Regel, die die Ports 3000 und 8080 für die HTW-Netze freigibt, lade das Regelwerk neu und prüfe, dass dein SSH-Zugang weiterhin funktioniert. Warum solltest du dabei die aktuelle SSH-Sitzung geöffnet lassen?
README.md, Abschnitt "Firewall")