Linux Firewall mit nftables 2026 – Modernes Setup

Warum nftables 2026 der Standard ist

Seit Kernel 5.13 ist nftables der offizielle Nachfolger von iptables, und spätestens 2026 gibt es kaum noch einen Grund, auf das alte Framework zu setzen. Debian 13, Ubuntu 24.04 LTS, RHEL 10 und AlmaLinux 10 liefern nftables als Default-Firewall-Backend aus. Der Kernel-Merge von xtables-nft bedeutet: selbst wenn du noch iptables-Befehle absetzt, werden sie intern in nftables-Regeln übersetzt.

Die Vorteile sind messbar. Ein Regelwerk mit 5.000 einzelnen IP-Blocks in iptables benötigt bei linearem Matching rund 1,2 ms pro Paket. Mit nftables-Sets und Hash-Lookup sinkt das auf unter 80 µs – also den Faktor 15. Bei einem Gameserver mit 2.000 gleichzeitigen UDP-Paketen pro Sekunde ist das der Unterschied zwischen 12 % und 0,8 % CPU-Last nur für die Firewall.

Dazu kommt die atomare Regel-Anwendung: nft -f ruleset.nft lädt das komplette Regelwerk in einer einzigen Transaktion. Kein Zwischenzustand, in dem Pakete durchfallen. Für DevOps-Workflows mit Ansible oder Terraform ist das ein enormer Vorteil gegenüber dem zeilenweisen iptables -A.

In diesem Guide baust du ein produktives Setup auf, das auf einem 5-Euro-VPS genauso läuft wie auf einem dedizierten 64-Core-Server bei Hetzner für 180 Euro im Monat.

Installation und Kernel-Voraussetzungen

Prüfe zuerst deine Kernel-Version. nftables benötigt mindestens Kernel 3.13, produktiv empfehlen wir aber 5.15 LTS oder neuer. Auf einem aktuellen Debian 13 oder Ubuntu 24.04 ist alles dabei.

uname -r
# 6.8.0-45-generic

apt update && apt install -y nftables
systemctl enable --now nftables

nft --version
# nftables v1.0.9 (Old Doc Yak #3)

Auf RHEL/AlmaLinux heißt das Paket ebenfalls nftables, allerdings ist dort firewalld als Frontend vorinstalliert. Wenn du direkt mit nftables arbeiten willst, deaktiviere firewalld:

dnf install -y nftables
systemctl disable --now firewalld
systemctl enable --now nftables

Prüfe, ob andere Firewall-Tools stören: ufw, firewalld oder alte iptables-Skripte können parallel Regeln setzen. Ein nft list ruleset auf einem frischen System sollte leer oder nur Docker-Ketten enthalten.

Die nftables-Architektur verstehen: Tables, Chains, Rules

nftables organisiert alles hierarchisch. Eine Table ist ein Namespace, der einer Address Family zugeordnet ist: ip (IPv4), ip6 (IPv6), inet (beide), arp, bridge oder netdev. Für die meisten Setups nimmst du inet, damit eine einzige Regel beide Protokolle abdeckt.

Innerhalb einer Table liegen Chains. Es gibt drei Typen: filter für normales Paketfiltering, nat für Source- und Destination-NAT, und route für Routing-Entscheidungen. Zusätzlich unterscheidet man Base Chains (mit Hook an input, forward, output, prerouting, postrouting) und Regular Chains (ohne Hook, nur per jump erreichbar).

Jede Chain hat eine Priority. Negative Zahlen laufen früher. Die Standardwerte sind: raw = -300, mangle = -150, dstnat = -100, filter = 0, srcnat = 100. Wenn du mehrere Chains am selben Hook hast, bestimmt die Priority die Reihenfolge.

Regeln selbst bestehen aus Match-Ausdrücken und einer Verdict-Anweisung: accept, drop, reject, jump, goto oder return. Wichtig: drop verwirft lautlos, reject sendet eine ICMP-Nachricht zurück. Für öffentlich erreichbare Ports ist drop die bessere Wahl, weil es Scannern keine Information liefert.

Ein minimales, sicheres Basis-Regelwerk

Das folgende Regelwerk ist ein solider Startpunkt für einen Webserver oder Gameserver. Es erlaubt etablierte Verbindungen, SSH, HTTP, HTTPS und ICMP – alles andere wird verworfen.

#!/usr/sbin/nft -f

flush ruleset

table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;

        iif lo accept
        ct state established,related accept
        ct state invalid drop

        ip protocol icmp accept
        ip6 nexthdr icmpv6 accept

        tcp dport { 22, 80, 443 } ct state new accept

        # Rate-Limit SSH-Bruteforce
        tcp dport 22 ct state new limit rate 4/minute burst 6 packets accept

        log prefix "nft-drop: " level warn
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
    }

    chain output {
        type filter hook output priority 0; policy accept;
    }
}

Speichere das als /etc/nftables.conf und lade es mit nft -f /etc/nftables.conf. Die ct state-Regeln sind entscheidend: ohne sie müsstest du für jede ausgehende Verbindung eine Rückrichtung explizit erlauben.

Die limit rate 4/minute-Regel ist ein einfacher Schutz gegen SSH-Bruteforce. Sie erlaubt nur vier neue Verbindungen pro Minute pro Quell-IP. Für einen Fail2ban-Ersatz reicht das in vielen Fällen aus, ohne zusätzlichen Daemon.

Achte darauf, dass die Policy auf drop steht – nicht auf accept. Eine Firewall, die standardmäßig alles erlaubt, ist keine Firewall.

Sets: tausende IPs in einer Regel

Sets sind der größte Performance-Gewinn von nftables. Statt 500 einzelne ip saddr-Regeln zu schreiben, packst du alle Adressen in ein Set mit O(1)-Lookup.

table inet filter {
    set blacklist {
        type ipv4_addr
        flags interval
        elements = { 10.0.0.0/8, 172.16.0.0/12,
                     192.168.0.0/16, 203.0.113.42 }
    }

    set ssh_ratelimit {
        type ipv4_addr
        flags dynamic, timeout
        timeout 1h
    }

    chain input {
        type filter hook input priority 0; policy drop;

        ip saddr @blacklist drop
        tcp dport 22 ct state new \
            add @ssh_ratelimit { ip saddr limit rate 5/minute } accept
    }
}

Das blacklist-Set mit flags interval erlaubt CIDR-Bereiche. Das ssh_ratelimit-Set ist dynamisch: jede IP, die mehr als fünf Verbindungen pro Minute aufbaut, landet für eine Stunde im Set und wird geblockt. Das ersetzt Fail2ban in vielen Szenarien komplett.

Du kannst Sets auch zur Laufzeit füllen, etwa aus einem Threat-Feed:

nft add element inet filter blacklist { 198.51.100.0/24 }
nft list set inet filter blacklist

Bei 100.000 Einträgen im Set bleibt der Lookup konstant bei rund 60 ns – unabhängig von der Set-Größe. Genau hier liegt der Vorteil gegenüber iptables-Ketten.

Maps: Port-Forwarding ohne Regel-Chaos

Maps sind wie Sets, nur mit einem Wert pro Schlüssel. Ideal für Port-Forwarding oder DNAT auf mehrere Backend-Server.

table ip nat {
    map portfwd {
        type inet_service : ipv4_addr . inet_service
        elements = {
            8080 : 10.0.0.10 . 80,
            8443 : 10.0.0.11 . 443,
            25565 : 10.0.0.20 . 25565
        }
    }

    chain prerouting {
        type nat hook prerouting priority dstnat; policy accept;
        dnat to tcp dport map @portfwd
    }
}

Damit leitest du Port 8080 auf einen internen Webserver, 8443 auf einen zweiten und 25565 auf einen Minecraft-Server um – alles in einer einzigen Regel. Bei iptables bräuchtest du drei separate DNAT-Regeln plus drei Forward-Regeln.

Vergiss bei DNAT nicht die Forward-Chain. Ohne eine Regel wie ct state established,related accept in der Forward-Chain wird das weitergeleitete Paket verworfen.

NAT, Routing und IPv6

Für einen Router oder VPN-Gateway brauchst du Masquerading. Das ist Source-NAT mit automatischer Adresswahl:

table ip nat {
    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
        oifname "eth0" masquerade
    }
}

Wichtig: Aktiviere IP-Forwarding im Kernel, sonst greift die Forward-Chain nie.

sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.d/99-forward.conf

Für IPv6 gilt dasselbe mit net.ipv6.conf.all.forwarding=1. Achte darauf, dass deine inet-Table beide Protokolle abdeckt. Ein häufiger Fehler: IPv4 ist dicht, IPv6 steht offen. Prüfe mit nft list ruleset, ob wirklich beide Familien Regeln haben.

Bei einem WireGuard-Setup auf einem 4-Euro-VPS reicht Masquerading plus eine Forward-Regel für wg0. Der Durchsatz liegt auf einem Hetzner CX22 (2 vCPU, 4 GB RAM) bei rund 850 Mbit/s – die Firewall ist dabei nicht der Flaschenhals.

Docker und Container-Integration

Docker setzt seit Version 28 standardmäßig auf nftables statt iptables. Das ist gut, bringt aber eine Falle: Docker erstellt eigene Tables (ip nat, ip filter) und hängt sich in die Forward-Chain. Wenn deine eigene Forward-Policy drop ist, bricht der Container-Traffic zusammen.

Die saubere Lösung ist eine eigene Base Chain mit niedrigerer Priority, die Docker-Traffic explizit akzeptiert:

table inet filter {
    chain forward {
        type filter hook forward priority 0; policy drop;
        ct state established,related accept
        iifname "docker0" accept
        oifname "docker0" accept
        iifname "br-*" accept
        oifname "br-*" accept
    }
}

Alternativ kannst du Dockers iptables-Manipulation komplett abschalten, wenn du kein Port-Mapping brauchst: {"iptables": false} in /etc/docker/daemon.json. Dann musst du aber alle Container-Ports selbst per DNAT freigeben.

Für Kubernetes mit kube-proxy im nftables-Modus (seit 1.31 stable) gilt: kube-proxy legt eigene Chains an. Überschreibe sie nicht mit flush ruleset – nutze stattdessen gezielte flush table inet filter-Befehle.

Logging, Monitoring und Debugging

nftables kann Pakete mit strukturierten Logs versehen. Für Fail2ban-kompatible Logs nutzt du das nftables-Log-Format:

chain input {
    type filter hook input priority 0; policy drop;
    tcp dport 22 ct state new limit rate 3/minute \
        log prefix "SSH-BRUTE: " level warn accept
}

# journalctl -k -f | grep SSH-BRUTE

Für Performance-Monitoring sind Counters nützlich. Jede Regel hat implizit einen Counter, den du mit nft -a list ruleset siehst. Explizite Counter helfen beim Debugging:

nft add rule inet filter input tcp dport 443 counter accept
nft list chain inet filter input
# ... tcp dport 443 counter packets 128934 bytes 89234512 accept

Für Grafana-Dashboards exportiert node_exporter seit Version 1.8 nftables-Metriken, wenn du --collector.nftables aktivierst. Damit siehst du Drop-Raten pro Chain live im Dashboard. Ein typischer Gameserver hat 0,1 bis 2 % Drops – deutlich mehr deutet auf einen Scan oder DDoS hin.

Zum Debuggen einzelner Pakete nutzt du nft monitor trace zusammen mit einer meta nftrace set 1-Regel. Das zeigt dir genau, welche Regel ein Paket akzeptiert oder verwirft.

Migration von iptables zu nftables

Die Migration ist einfacher als viele denken. Das Tool iptables-nft-restore und iptables-translate helfen:

iptables-translate -A INPUT -p tcp --dport 22 -j ACCEPT
# nft add rule ip filter INPUT tcp dport 22 counter accept

iptables-save > /tmp/iptables.rules
iptables-restore-translate -f /tmp/iptables.rules > /tmp/nftables.rules
nft -f /tmp/nftables.rules

Prüfe das Ergebnis immer manuell. Komplexe Regeln mit recent, hashlimit oder string-Match werden nicht 1:1 übersetzt. Diese musst du durch native nftables-Äquivalente ersetzen – recent durch dynamische Sets, hashlimit durch limit rate.

Ein bewährter Ansatz: Baue das nftables-Regelwerk parallel auf, teste es mit nft -c -f ruleset.nft (Dry-Run), und schalte erst dann um. Bei einem Managed-Server mit 200 Kunden kannst du so ohne Downtime migrieren.

Vergiss nicht die Persistenz: systemctl enable nftables sorgt dafür, dass /etc/nftables.conf beim Boot geladen wird. Auf Debian und Ubuntu ist das der Standardpfad, auf RHEL liest der Service ebenfalls diese Datei.

Performance-Tuning und typische Fallstricke

nftables skaliert linear mit der Regelanzahl, aber Sets skalieren konstant. Faustregel: alles, was mehr als zehn Einträge hat, gehört in ein Set. Ein Regelwerk mit 200 Einzelregeln kostet auf einem 8-Core-Server rund 4 % CPU bei 100.000 Paketen pro Sekunde – mit Sets sind es unter 0,5 %.

Weitere Optimierungen:

Typische Fallstricke: vergessene IPv6-Regeln, Docker-Forward-Konflikte, und flush ruleset in Skripten, das fremde Tables mitlöscht. Nutze stattdessen flush table inet filter oder arbeite mit nft -f und atomaren Transaktionen.

Praxis-Setup: Gameserver mit DDoS-Schutz

Ein typisches Gameserver-Setup auf einem Hetzner AX42 (8 vCPU, 64 GB RAM, 49 Euro/Monat) sieht so aus: SSH nur per Key, Rate-Limit auf Verbindungen, UDP-Set für bekannte Angreifer-IPs, und ein Conntrack-Limit pro IP.

table inet filter {
    set udp_flood {
        type ipv4_addr
        flags dynamic, timeout
        timeout 10m
    }

    chain input {
        type filter hook input priority 0; policy drop;
        ct state established,related accept
        ct state invalid drop

        # UDP-Flood-Schutz
        udp dport 27015 ct state new \
            add @udp_flood { ip saddr limit rate over 200/second } drop

        tcp dport { 22, 25565, 27015 } ct state new accept
    }
}

Diese Regel erlaubt 200 UDP-Pakete pro Sekunde pro IP auf den Gameserver-Port. Alles darüber landet für zehn Minuten im Set und wird verworfen. Bei einem Minecraft-Server mit 50 Spielern liegt der Normalwert bei 20 bis 40 Paketen pro Sekunde – der Schwellwert ist also großzügig.

Kombiniere das mit einem externen DDoS-Filter (OVH Game, Path.net ab 30 Euro/Monat) für volumetrische Angriffe. nftables schützt gegen Layer-4-Floods im Applikationsbereich, nicht gegen 500-Gbit/s-Angriffe.

FAQ

Ist nftables schneller als iptables?

Bei einfachen Regelwerken sind beide vergleichbar. Der Vorteil zeigt sich ab etwa 100 Regeln: nftables nutzt Hash-Lookups für Sets und Maps, iptables arbeitet linear. Bei 5.000 IP-Blocks ist nftables rund 15-mal schneller. Zusätzlich ist die atomare Regel-Anwendung bei nftables ein echter Vorteil für automatisierte Deployments.

Kann ich nftables und iptables parallel nutzen?

Technisch ja, aber es ist eine schlechte Idee. Auf modernen Distributionen ist iptables ohnehin ein Wrapper um nftables (iptables-nft), und beide schreiben in dieselben Kernel-Strukturen. Mischbetrieb führt zu schwer debugbaren Regelkonflikten. Migriere vollständig oder bleibe bei einem Tool.

Wie mache ich mein nftables-Regelwerk persistent?

Schreibe die Regeln in /etc/nftables.conf und aktiviere den Service mit systemctl enable --now nftables. Auf Debian und Ubuntu ist das der Standardpfad. Auf RHEL-basierten Systemen liest der Service ebenfalls diese Datei. Änderungen zur Laufzeit gehen ohne Persistenz beim Reboot verloren.

Ersetzt nftables Fail2ban?

Für einfache Fälle ja. Dynamische Sets mit limit rate blocken Bruteforce-Versuche ohne zusätzlichen Daemon und ohne Log-Parsing. Fail2ban ist nur dann nötig, wenn du komplexe Log-Muster auswerten willst – etwa fehlgeschlagene Logins in Webanwendungen. Für SSH reicht die native nftables-Lösung.

Was kostet ein Server, auf dem nftables sinnvoll läuft?

nftables läuft auf jedem Linux ab Kernel 3.13. Ein 4-Euro-VPS (1 vCPU, 2 GB RAM) reicht für ein Regelwerk mit 10.000 Set-Einträgen locker aus. Für Routing mit Flowtable und hohem Durchsatz empfehlen wir mindestens 2 vCPU und 4 GB RAM – etwa einen Hetzner CX22 für rund 4 Euro oder einen Netcup VPS 1000 G11 für 6 Euro im Monat.