Nftables Webserver Beispiel: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
(Die Seite wurde neu angelegt: „<pre> #!/usr/sbin/nft -f # Flush existing rules flush ruleset # Define the main table for filtering table inet filter { # Input chain - handles incoming tr…“)
 
Zeile 1: Zeile 1:
 
<pre>
 
<pre>
 
#!/usr/sbin/nft -f
 
#!/usr/sbin/nft -f
 +
#
 +
# Gehärtete nftables-Config für einen Webserver
 +
# Änderungen ggü. Ausgangsversion:
 +
#  - ct state invalid wird explizit verworfen (nicht nur implizit durch policy drop)
 +
#  - Rate-Limiting gegen ICMP-Flood
 +
#  - SYN-Flood-Schutz für neue TCP-Verbindungen
 +
#  - Logging mit Rate-Limit (statt nur "counter drop")
 +
#  - Output-Chain: policy drop statt accept, nur benötigter ausgehender Traffic erlaubt
 +
#  - Webserver-Prozess (UID www-data) darf grundsätzlich KEINE ausgehenden
 +
#    Verbindungen aufbauen -> verhindert Reverse Shells, Malware-Downloads,
 +
#    C2-Callbacks im Falle einer Kompromittierung (z.B. via Webshell)
 +
#  - IPv6 ICMP nicht pauschal erlaubt, sondern nur die für den Betrieb nötigen Typen
 +
#
 +
# SSH (Port 22) wird bewusst NICHT weiter eingeschränkt (Source-IP-Filter,
 +
# Rate-Limit) - das wird laut Vorgabe separat/anders gehandhabt.
  
# Flush existing rules
+
flush ruleset
 +
 
 +
table inet filter {
 +
 
 +
    # UID des Webserver-Prozesses - ggf. anpassen (z.B. nginx: 33, oft auch
 +
    # eigener User statt www-data; mit `id www-data` bzw. `ps aux | grep nginx`
 +
    # prüfen, welcher User den Webserver-Prozess tatsächlich fährt)
 +
    define WEBSERVER_UID = 33
 +
 
 +
    chain input {
 +
        type filter hook input priority filter; policy drop;
 +
 
 +
        # Loopback immer erlauben
 +
        iif lo accept
 +
 
 +
        # Ungültige Pakete explizit verwerfen (nicht erst der Default-Policy
 +
        # überlassen - so lässt sich das auch gezielt loggen)
 +
        ct state invalid counter drop
 +
 
 +
        # Bestehende/verwandte Verbindungen erlauben
 +
        ct state established,related accept
 +
 
 +
        # SSH - unverändert offen, wird separat abgesichert
 +
        tcp dport 22 accept
 +
 
 +
        # HTTP/HTTPS mit SYN-Flood-Schutz: neue Verbindungen pro Quelle begrenzen
 +
        tcp dport { 80, 443 } ct state new limit rate 50/second burst 20 packets accept
 +
        tcp dport { 80, 443 } accept
 +
 
 +
        # ICMP für Diagnose, aber mit Rate-Limit gegen Ping-Flood
 +
        ip protocol icmp icmp type echo-request limit rate 10/second accept
 +
        ip protocol icmp accept
 +
 
 +
        # ICMPv6: nicht pauschal, sondern nur die für Betrieb/Neighbor Discovery
 +
        # nötigen Typen (bei IPv6 essenziell, sonst brechen NDP/SLAAC/PMTU)
 +
        ip6 nexthdr icmpv6 icmpv6 type {
 +
            destination-unreachable,
 +
            packet-too-big,
 +
            time-exceeded,
 +
            parameter-problem,
 +
            echo-request,
 +
            echo-reply,
 +
            nd-router-solicit,
 +
            nd-router-advert,
 +
            nd-neighbor-solicit,
 +
            nd-neighbor-advert
 +
        } accept
 +
 
 +
        # Alles andere: mit Rate-limitiertem Logging verwerfen
 +
        limit rate 5/minute log prefix "nft-input-drop: " counter drop
 +
    }
 +
 
 +
    chain forward {
 +
        type filter hook forward priority filter; policy drop;
 +
    }
 +
 
 +
    chain output {
 +
        type filter hook output priority filter; policy drop;
 +
 
 +
        # Loopback
 +
        oif lo accept
  
flush ruleset
+
        # Bestehende/verwandte Verbindungen (Antworten auf eingehende Requests,
 +
        # z.B. HTTP-Responses) erlauben - aber s. u., für WEBSERVER_UID gesperrt
 +
        ct state established,related accept
 +
 
 +
        # --- Webserver-Prozess: keinerlei neue ausgehende Verbindungen ---
 +
        # Das muss VOR den allgemeinen "erlauben"-Regeln stehen, damit es
 +
        # nicht durch established,related o.ä. unterlaufen wird. Auch
 +
        # established/related wird für diese UID hier schon effektiv verhindert,
 +
        # da der Webserver ja nie eine ausgehende Verbindung initiieren darf,
 +
        # aus der ein "established" Zustand entstehen könnte.
 +
        meta skuid $WEBSERVER_UID counter log prefix "nft-webserver-egress-blocked: " drop
 +
 
 +
        # Ab hier: regulärer System-Traffic (läuft NICHT unter WEBSERVER_UID)
 +
        # DNS-Auflösung
 +
        udp dport 53 accept
 +
        tcp dport 53 accept
  
# Define the main table for filtering
+
        # NTP für Zeitsynchronisation
 +
        udp dport 123 accept
  
table inet filter {
+
        # HTTPS für Paket-Updates, externe API-Calls des Systems etc.
# Input chain - handles incoming traffic
+
        tcp dport 443 accept
chain input {
 
type filter hook input priority filter; policy drop;
 
    # Accept loopback traffic
 
    iif lo accept
 
   
 
    # Accept established and related connections
 
    ct state established,related accept
 
   
 
    # Accept SSH (port 22) - consider limiting to specific IPs in production
 
    tcp dport 22 accept
 
   
 
    # Accept HTTP (port 80)
 
    tcp dport 80 accept
 
   
 
    # Accept HTTPS (port 443)
 
    tcp dport 443 accept
 
 
 
    # Accept ICMP for ping and network diagnostics
 
    ip protocol icmp accept
 
    ip6 nexthdr icmpv6 accept
 
   
 
    # Log and drop everything else (optional logging)
 
    # counter log prefix "nftables-dropped: " drop
 
    counter drop
 
}
 
  
# Forward chain - for routing (usually not needed for web servers)
+
        # SSH-Verbindungen vom System selbst nach außen (z.B. für Admin-Zwecke),
chain forward {
+
        # bei Bedarf entfernen, falls nicht benötigt
    type filter hook forward priority filter; policy drop;
+
        tcp dport 22 accept
}
 
  
# Output chain - handles outgoing traffic
+
        # ICMP für Diagnosezwecke (ping, traceroute vom Host aus)
chain output {
+
        ip protocol icmp accept
    type filter hook output priority filter; policy accept;
+
        ip6 nexthdr icmpv6 accept
   
 
    # Allow all outgoing traffic by default
 
    # You can add restrictions here if needed
 
}
 
  
 +
        # Alles andere ausgehende: loggen und verwerfen
 +
        limit rate 5/minute log prefix "nft-output-drop: " counter drop
 +
    }
 
}
 
}
 
</pre>
 
</pre>

Version vom 3. August 2026, 07:28 Uhr

#!/usr/sbin/nft -f
#
# Gehärtete nftables-Config für einen Webserver
# Änderungen ggü. Ausgangsversion:
#   - ct state invalid wird explizit verworfen (nicht nur implizit durch policy drop)
#   - Rate-Limiting gegen ICMP-Flood
#   - SYN-Flood-Schutz für neue TCP-Verbindungen
#   - Logging mit Rate-Limit (statt nur "counter drop")
#   - Output-Chain: policy drop statt accept, nur benötigter ausgehender Traffic erlaubt
#   - Webserver-Prozess (UID www-data) darf grundsätzlich KEINE ausgehenden
#     Verbindungen aufbauen -> verhindert Reverse Shells, Malware-Downloads,
#     C2-Callbacks im Falle einer Kompromittierung (z.B. via Webshell)
#   - IPv6 ICMP nicht pauschal erlaubt, sondern nur die für den Betrieb nötigen Typen
#
# SSH (Port 22) wird bewusst NICHT weiter eingeschränkt (Source-IP-Filter,
# Rate-Limit) - das wird laut Vorgabe separat/anders gehandhabt.

flush ruleset

table inet filter {

    # UID des Webserver-Prozesses - ggf. anpassen (z.B. nginx: 33, oft auch
    # eigener User statt www-data; mit `id www-data` bzw. `ps aux | grep nginx`
    # prüfen, welcher User den Webserver-Prozess tatsächlich fährt)
    define WEBSERVER_UID = 33

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

        # Loopback immer erlauben
        iif lo accept

        # Ungültige Pakete explizit verwerfen (nicht erst der Default-Policy
        # überlassen - so lässt sich das auch gezielt loggen)
        ct state invalid counter drop

        # Bestehende/verwandte Verbindungen erlauben
        ct state established,related accept

        # SSH - unverändert offen, wird separat abgesichert
        tcp dport 22 accept

        # HTTP/HTTPS mit SYN-Flood-Schutz: neue Verbindungen pro Quelle begrenzen
        tcp dport { 80, 443 } ct state new limit rate 50/second burst 20 packets accept
        tcp dport { 80, 443 } accept

        # ICMP für Diagnose, aber mit Rate-Limit gegen Ping-Flood
        ip protocol icmp icmp type echo-request limit rate 10/second accept
        ip protocol icmp accept

        # ICMPv6: nicht pauschal, sondern nur die für Betrieb/Neighbor Discovery
        # nötigen Typen (bei IPv6 essenziell, sonst brechen NDP/SLAAC/PMTU)
        ip6 nexthdr icmpv6 icmpv6 type {
            destination-unreachable,
            packet-too-big,
            time-exceeded,
            parameter-problem,
            echo-request,
            echo-reply,
            nd-router-solicit,
            nd-router-advert,
            nd-neighbor-solicit,
            nd-neighbor-advert
        } accept

        # Alles andere: mit Rate-limitiertem Logging verwerfen
        limit rate 5/minute log prefix "nft-input-drop: " counter drop
    }

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

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

        # Loopback
        oif lo accept

        # Bestehende/verwandte Verbindungen (Antworten auf eingehende Requests,
        # z.B. HTTP-Responses) erlauben - aber s. u., für WEBSERVER_UID gesperrt
        ct state established,related accept

        # --- Webserver-Prozess: keinerlei neue ausgehende Verbindungen ---
        # Das muss VOR den allgemeinen "erlauben"-Regeln stehen, damit es
        # nicht durch established,related o.ä. unterlaufen wird. Auch
        # established/related wird für diese UID hier schon effektiv verhindert,
        # da der Webserver ja nie eine ausgehende Verbindung initiieren darf,
        # aus der ein "established" Zustand entstehen könnte.
        meta skuid $WEBSERVER_UID counter log prefix "nft-webserver-egress-blocked: " drop

        # Ab hier: regulärer System-Traffic (läuft NICHT unter WEBSERVER_UID)
        # DNS-Auflösung
        udp dport 53 accept
        tcp dport 53 accept

        # NTP für Zeitsynchronisation
        udp dport 123 accept

        # HTTPS für Paket-Updates, externe API-Calls des Systems etc.
        tcp dport 443 accept

        # SSH-Verbindungen vom System selbst nach außen (z.B. für Admin-Zwecke),
        # bei Bedarf entfernen, falls nicht benötigt
        tcp dport 22 accept

        # ICMP für Diagnosezwecke (ping, traceroute vom Host aus)
        ip protocol icmp accept
        ip6 nexthdr icmpv6 accept

        # Alles andere ausgehende: loggen und verwerfen
        limit rate 5/minute log prefix "nft-output-drop: " counter drop
    }
}