Zum Inhalt

Stateful Packet Filtering mit nftables & UFW: Netfilter-Hooks & Connection Tracking

Erstellt: 08.11.2026  ·  Zuletzt aktualisiert: 08.11.2026  ·  Nejat Hakan

Management Summary: Hinter jeder Linux-Firewall arbeitet das Netfilter-Subsystem des Linux-Kernels. Über zwei Jahrzehnte hinweg kämpften Administratoren mit den Altlasten von iptables, ip6tables und arptables – separaten Werkzeugen, die Regeln sequenziell mit hohem Performanceverlust abarbeiteten. In modernen Linux-Distributionen (Debian 11/12+) stellt nftables eine einheitliche Bytecode-Virtual-Machine im Kernel bereit. Sie bietet atomare Regel-Updates, Dual-Stack-Filterung (inet) für IPv4 und IPv6, Suchoperationen in konstanter Zeit (O(1)) sowie tiefgehende Verbindungsverfolgung (conntrack).

  • Netfilter-Kernel-Hooks


    Die 5 elementaren Abfangpunkte im Kernel-Paketfluss: PREROUTING, INPUT, FORWARD, OUTPUT und POSTROUTING.

  • nftables-Architektur


    Die einheitliche inet-Familie, Basis-Chains, Verdict-Maps, dynamische Sets für Rate-Limiting und atomare Transaktionen im laufenden Betrieb.

  • Stateful conntrack


    Pakete anhand ihres Sitzungsstatus filtern: NEW, ESTABLISHED, RELATED und INVALID, um interne Systeme zuverlässig abzuschotten.

  • UFW für Edge-Knoten


    Verwaltung über die Uncomplicated Firewall (ufw): Standard-Policies, Anwendungs-Profile und schnittstellenspezifische Freigaben.


1. Das Netfilter-Subsystem: Die 5 Paket-Hooks des Linux-Kernels

Der Linux-Kernel leitet eingehende, geroutete und ausgehende Netzwerkpakete durch fünf feste Kontrollpunkte (Netfilter-Hooks):

%%{init: {'flowchart': {'wrappingWidth': 350}}}%%
flowchart TB
    NIC_IN["Eingehendes Paket (RX Ring)"] --> PRE["1. PREROUTING Hook<br/>DNAT / Port-Forwarding"]
    PRE --> DEC{"Ziel-IP?"}
    DEC -->|"Lokale IP"| INP["2. INPUT Hook<br/>Schützt lokale Dienste"]
    DEC -->|"Fremde IP"| FWD["3. FORWARD Hook<br/>Router / VM / Container"]
    INP --> APP["Lokaler App-Socket<br/>(Nginx, SSHd)"]
    APP --> OUT["4. OUTPUT Hook<br/>Lokaler Ausgangsverkehr"]
    OUT --> ROUTE_OUT["Reroute Check"]
    ROUTE_OUT --> POST["5. POSTROUTING Hook<br/>SNAT / Masquerading"]
    FWD --> POST
    POST --> NIC_OUT["Ausgehendes Paket (TX Ring)"]

Die 5 Netfilter-Hooks im Detail

  1. PREROUTING: Fängt Pakete unmittelbar nach dem Empfang durch den Netzwerkkartentreiber ab, noch vor jeder Routing-Entscheidung. Hauptanwendungsgebiet ist Destination-NAT (DNAT) und Port-Forwarding.
  2. INPUT: Wird für alle Pakete durchlaufen, die für einen lokalen Prozess auf dem Server bestimmt sind. Hier greift die klassische Host-Firewall zum Schutz lokaler Dienste.
  3. FORWARD: Greift für Pakete, deren Ziel-IP auf einem anderen Host liegt. Wird aktiv, wenn der Linux-Server als Router, Gateway oder Container-Host agiert.
  4. OUTPUT: Verarbeitet Pakete, die von lokalen Prozessen erzeugt wurden, bevor sie das System über das Routing verlassen.
  5. POSTROUTING: Wird nach allen Routing-Entscheidungen durchlaufen, unmittelbar bevor das Paket auf das physische Kabel gelegt wird. Dient für Source-NAT (SNAT) und IP-Masquerading.

2. Warum nftables das alte iptables ablöst

Funktion Veraltetes iptables Modernes nftables
Protokoll-Familien 4 getrennte Tools (iptables, ip6tables, arptables, ebtables). Einheitliche inet-Familie verarbeitet IPv4 und IPv6 gemeinsam in einer einzigen Regel.
Prüfgeschwindigkeit Linearer Scan: Regeln werden zeilenweise von oben nach unten geprüft (O(n)). Sets in konstanter Zeit (O(1)) über interne Hashing- und Baumstrukturen.
Regel-Aktualisierung Nicht atomar: Änderungen erfordern das schrittweise Neu-Laden von Chains. Strikte atomare Transaktionen: Die gesamte /etc/nftables.conf wird unterbrechungsfrei im RAM getauscht.
Architektur Fest eincompilierter C-Code im Kernel für jedes Modul. Schlanke Bytecode-Virtual-Machine im Kernel, gesteuert über User-Space-Syntax.
Port-Listen Mehrere Zeilen oder langsame multiport-Module. Native Mengennotation: tcp dport { 80, 443, 8080 } accept.

3. Zustandshafte Verbindungsverfolgung (conntrack)

Ein zustandsloser Paketfilter betrachtet jedes Paket isoliert. Eine stateful Firewall hingegen verfolgt den Lebenszyklus von Verbindungen im Kernel-RAM (conntrack-Tabelle):

%%{init: {'flowchart': {'wrappingWidth': 350}}}%%
flowchart TB
    PKT["Eingehendes Paket"] --> CT["conntrack-Tabelle"]
    CT --> STATE{"Aktive Session?"}
    STATE -->|"ESTABLISHED / RELATED"| ACC["Sofortiges ACCEPT<br/>Bestehende Session"]
    STATE -->|"Nein"| CHK{"Gültiges Paket?"}
    CHK -->|"INVALID"| DRP["Sofortiges DROP<br/>Fehlerhafte Flags"]
    CHK -->|"NEW"| RULE["Regelwerk prüfen<br/>Ports, Rates, Policies"]

Die 4 zentralen Verbindungszustände

  • NEW: Das Paket initiiert eine neue Verbindung (z. B. ein TCP-SYN-Paket).
  • ESTABLISHED: Das Paket gehört zu einer bereits bestehenden, in beide Richtungen bestätigten Verbindung (z. B. nach dem TCP-Handshake).
  • RELATED: Das Paket gehört zu einer neuen Verbindung, die jedoch mit einer bestehenden in Beziehung steht (z. B. ICMP-Fehlermeldungen wie Destination Unreachable).
  • INVALID: Das Paket widerspricht den Protokollregeln oder kann nicht zugeordnet werden. Muss immer sofort verworfen werden.

4. Produktiv-Konfiguration: /etc/nftables.conf

Diese praxiserprobte /etc/nftables.conf für Debian-Server schützt IPv4 und IPv6 in einer gemeinsamen Tabelle, wehrt Brute-Force-Angriffe über dynamische Rate-Limiting-Sets ab und lässt essenziellen ICMPv6-Verkehr passieren:

#!/usr/sbin/nft -f
# Datei: /etc/nftables.conf

# Bestehende Tabellen atomar verwerfen
flush ruleset

table inet filter {
    # Dynamisches Set gegen SSH-Brute-Force
    set ssh_meter {
        type ipv4_addr
        flags dynamic, timeout
        timeout 1m
    }

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

        # 1. Bestehende und zugehörige Verbindungen performant erlauben
        ct state established,related accept

        # 2. Fehlerhafte Pakete sofort verwerfen
        ct state invalid drop

        # 3. Lokalen Loopback-Verkehr vollständig gestatten
        iifname "lo" accept

        # 4. ICMP & ICMPv6 (ESSENZIELL für IPv6 Path-MTU und NDP)
        ip protocol icmp icmp type { echo-request, destination-unreachable, time-exceeded } limit rate 10/second accept
        ip6 nexthdr icmpv6 icmpv6 type {
            destination-unreachable, packet-too-big, time-exceeded,
            parameter-problem, echo-request, nd-router-advert,
            nd-neighbor-solicit, nd-neighbor-advert
        } accept

        # 5. OpenSSH (Port 22) mit automatischem Brute-Force-Schutz
        # Erlaubt maximal 6 neue Verbindungsversuche pro Minute je Quell-IP
        tcp dport 22 ct state new add @ssh_meter { ip saddr limit rate 6/minute } accept

        # 6. Öffentliche Webdienste (HTTP & HTTPS)
        tcp dport { 80, 443 } accept

        # 7. Zähler für alle verworfenen Pakete
        counter drop
    }

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

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

Konfiguration testen und aktivieren

# Syntax prüfen (ohne Änderungen am Kernel)
sudo nft -c -f /etc/nftables.conf

# Regelwerk atomar anwenden
sudo nft -f /etc/nftables.conf

# Systemd-Dienst für automatischen Start aktivieren
sudo systemctl enable --now nftables

5. Die Alternative für Edge-Knoten: Uncomplicated Firewall (UFW)

Auf Standalone-Servern oder Entwicklungs-Maschinen bietet UFW eine einfache, befehlsbasierte Administration:

# UFW unter Debian installieren
sudo apt update && sudo apt install -y ufw

# 1. Strikte Standard-Richtlinien setzen
sudo ufw default deny incoming
sudo ufw default allow outgoing

# 2. SSH mit Rate-Limiting absichern
sudo ufw limit 22/tcp comment 'Rate-limited OpenSSH'

# 3. Web-Ports freigeben
sudo ufw allow 80/tcp comment 'HTTP ACME'
sudo ufw allow 443/tcp comment 'HTTPS Reverse Proxy'

# 4. Datenbankzugriff strikt auf internes Administrations-Subnetz beschränken
sudo ufw allow in on eth0 from 10.10.20.0/24 to any port 5432 proto tcp comment 'Interne Postgres-DB'

# 5. Firewall aktivieren
sudo ufw enable

UFW im laufenden Betrieb verwalten

# Aktive Regeln nummeriert auflisten
sudo ufw status numbered

# Regel anhand ihrer Zeilennummer löschen
sudo ufw delete 4

# Detaillierten Status inklusive Logging-Level anzeigen
sudo ufw status verbose

6. Live-Diagnose und Überwachung

1. Paketverluste in Echtzeit beobachten

# Netfilter-Ereignisse live im Terminal streamen
sudo nft monitor

2. Aktive Sessions in der conntrack-Tabelle einsehen

sudo apt install -y conntrack
# Alle aktiven TCP-Sitzungen anzeigen
sudo conntrack -L -p tcp

7. Nächste Schritte

Nachdem der Server perimeterseitig durch Stateful Firewalls geschützt ist, geht es an die abhörsichere Vernetzung entfernter Standorte über moderne Kernel-Tunnel:

  • WireGuard: Kernel-VPN & Cryptokey Routing


    Moderne Punkt-zu-Punkt- und Site-to-Site-Tunnel mit wireguard.ko, Noise-Protokoll und AllowedIPs-Routing aufsetzen.

    Zum WireGuard-Leitfaden