nftables Configuration Starter Template · March 2025 'thx stfn' beta version

This customizable code snippet can be easily edited and copied using the buttons provided. Simply paste it into your /etc/nftables.conf file to configure your nftables as required.

#!/usr/sbin/nft -f

# On Debian 12 integrates with sshguard for enhanced security.
# Uses 'inet' family for dual-stack IPv4/IPv6 support.

# VLANs, sub-interfaces or source address filtering can be used to define trust too.
define trusted_ifaces = { "lo", "br-int", "bond0", "eth1", "eth2" } # Define trusted interfaces (modify these to match your internal or management interfaces)
define trusted_routers = { "fe80::1", "fe80::2" } # Define designated routers (their link-local IPv6 addresses; adjust as needed)

table inet filter {
  set allowed_tcp_ports {
    type inet_service;  # Use inet_service for service/port numbers - do NOT list ssh (22) here
    elements = { 80, 443 };
  }

  set allowed_udp_ports {
    type inet_service;
    # elements = { };  # Omit elements line if no initial values are present
  }

  set trusted_ssh_ips {
    type ipv4_addr;  # Set of IPv4 addresses allowed for privileged SSH access
    flags interval;
    elements = {
      192.0.2.0/24,
      198.51.100.0/24,
      203.0.113.0/29
    };
  }

  set blacklist {
    type ipv4_addr;
    timeout 1h;  # Adjust timeout as necessary
  }
	
  chain input {
    type filter hook input priority 0; policy drop;

    # Allow all traffic on the loopback interface for internal communications
    iifname "lo" accept;
    iifname != "lo" ip daddr 127.0.0.1/8 drop;  # Prevent spoofing to localhost
    iifname != "lo" ip6 daddr ::1 drop;

    # Manage ongoing connections, drop malformed packets
    ct state {established, related} accept;
    ct state invalid log prefix "Invalid packet: " drop;

    # Prevent spoofing from localhost IP addresses
    ip saddr 127.0.0.0/8 drop;
    ip6 saddr ::1/128 drop;

    # Block bogon IP ranges (non-routable)
    # ip saddr { 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 169.254.0.0/16, 172.16.0.0/12, 192.168.0.0/16, 224.0.0.0/4, 240.0.0.0/4 } drop;
    # have to exclude 172.30.0.0/16 that's internally used and routed
    ip saddr { 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 169.254.0.0/16, 172.16.0.0/13, 172.24.0.0/14, 172.28.0.0/15, 172.31.0.0/16, 192.168.0.0/16, 224.0.0.0/4, 240.0.0.0/4 } drop;
    # ip6 saddr { ::/128, fc00::/7, fe80::/10, ff00::/8 } drop;
    # Drop spoofed IPv6 packets on untrusted interfaces only
    iifname not @trusted_ifaces ip6 saddr { ::/128, fc00::/7, fe80::/10, ff00::/8 } drop
	
    # Allow SSH access from IPs specified in 'trusted_ssh_ips'
    ip saddr @trusted_ssh_ips tcp dport 22 accept;

    # Rate limiting for new SSH connections to protect against brute-force attacks
    tcp dport 22 ct state new limit rate 3/minute burst 5 packets accept;
    tcp dport 22 ct state new log prefix "SSH rate limit exceeded: " level info drop;

    # Allow and manage TCP and UDP traffic on common service ports
    tcp dport @allowed_tcp_ports accept;
    udp dport @allowed_udp_ports accept;

    # Mitigate SYN floods with rate limiting for new TCP SYN packets
    ip protocol tcp tcp flags syn ct state new limit rate 8/second burst 24 packets accept;
	
    # Drop packets with no standard TCP flags set
    ip protocol tcp tcp flags & (fin|syn|rst|ack) == 0 log prefix "Empty TCP flags: " level info drop;

    # Additional protection against common TCP attacks
    ip protocol tcp tcp flags & (fin|psh|urg) == (fin|psh|urg) add @blacklist { ip saddr } log prefix "XMAS scan: " drop;
    ip protocol tcp tcp flags & (fin) == fin add @blacklist { ip saddr } log prefix "FIN scan: " drop;
    ip protocol tcp tcp flags & (syn|fin) == (syn|fin) add @blacklist { ip saddr } log prefix "SYN-FIN scan: " drop;
    ip protocol tcp tcp flags & (fin|syn|rst|ack) == 0 add @blacklist { ip saddr } log prefix "NULL scan: " drop;

    # Drop new connections that do not start with SYN
    ip protocol tcp ct state new tcp flags != syn log prefix "New non-SYN packet: " drop;

    # Drop traffic from blacklisted IPs
    ip saddr @blacklist drop;

    # Allow and rate-limit ICMP (ping) to prevent abuse while allowing network testing
    ip protocol icmp icmp type { destination-unreachable, time-exceeded, parameter-problem } accept;
    ip protocol icmp icmp type echo-request limit rate 2/second burst 6 packets accept;

    # Specific rules for handling IPv6 traffic
    ip6 nexthdr icmpv6 icmpv6 type {1, 2, 3, 4} accept;  # Accept essential ICMPv6 messages for error handling
    ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate 2/second burst 6 packets accept;  # Limit Echo Requests to 1 per second
    ip6 nexthdr icmpv6 icmpv6 type echo-reply limit rate 10/minute accept;  # Limit Echo Replies to 10 per minute
    # ip6 nexthdr icmpv6 icmpv6 type 134 log prefix "Dropped RA: " drop;  # Log and drop Router Advertisements
    # Allow RA from designated routers (regardless of interface)
    ip6 nexthdr icmpv6 ip6 saddr @trusted_routers icmpv6 type 134 accept
    # Drop RA messages arriving on untrusted interfaces only
    iifname not @trusted_ifaces ip6 nexthdr icmpv6 icmpv6 type 134 log prefix "Dropped RA: " drop


    # Log and drop other denied incoming packets with rate limit for logs
    log prefix "Denied incoming: " level info limit rate 1/minute burst 4 packets drop;
  }

  # Forward chain: Typically empty unless configured as a router or WireGuard server
  chain forward {
    type filter hook forward priority 0; policy drop;
  }

  # Output chain: By default, allows all outgoing traffic														 
  chain output {
    type filter hook output priority 0; policy accept;

    # Allow new, established, and related connections
    ct state {new, established, related} accept;
  }
}

# Usage and Maintenance Notes:
# - Syntax check with `sudo nft -c -f /etc/nftables.conf`
# - View logs and debug with `journalctl -u nftables`
# - Enable and start with `systemctl enable nftables` and `systemctl start nftables`
# - Modify 'trusted_ssh_ips' to update SSH access control
# - Modify 'allowed_tcp_ports' and 'allowed_udp_ports'
# - reload the config to apply with `systemctl reload nftables`
#
# - To integrate with sshguard for dynamic IP blocking, ensure proper setup in /etc/sshguard/sshguard.conf
#   nft list tables // nft list table sshguard // systemctl cat sshguard // nft list ruleset
#   (apt install sshguard -y ; systemctl enable sshguard ; systemctl start sshguard)
#
# - This config does not include a flush rule to preserve dynamically managed tables (sshguard, etc)
#
# Additional Configuration Recommendations:
# - Implement granular access rules for critical services (e.g., database servers, administrative interfaces)
#   running on specific ports, akin to the SSH configuration, to enhance security and control.