[tor-relays] Re: DDoS solution for Tor nodes - nftables variant implemented

Yay, I've been wondering for years why you aren't using nftables. :wink:

2 hints:
- Use `auto-merge` and `interval` flag in dynamic sets.

- Block crazy packets like this in line 172, in chain 'ingress' before conntrack:
tcp flags & (syn|rst|ack|fin) != syn ct state new counter name "badflags" drop

Example:

table netdev filter {

  # List of ipv4 addresses to block.
  # add new IP: nft add element netdev filter blocklist_v4 \{ 192.168.20.20 \}
  # add new subnet: nft add element netdev filter blocklist_v4 \{ 192.168.22.0/24 \}
  # list elements: nft list set netdev filter blocklist_v4
  set blocklist_v4 {
    type ipv4_addr
    flags interval
    counter
    auto-merge
    elements = { 37.187.92.9, 81.201.60.130,
                 173.212.234.100 }
  }

  # List of ipv6 addresses to block.
  set blocklist_v6 {
    type ipv6_addr
    flags interval
    counter
    auto-merge
  }

  chain ingress {
    type filter hook ingress devices = { enp4s0f0, enp4s0f1 } priority -500;

    # Drop all IP FRAGMENTS
    ip frag-off & 0x1fff != 0 counter drop

    # Drop DDoS IPs
    ip saddr @blocklist_v4 counter drop
    ip6 saddr @blocklist_v6 counter drop

    # Drop TCP XMAS packets.
    tcp flags & (fin|syn|rst|psh|ack|urg) == fin|syn|rst|psh|ack|urg counter drop

    # Drop TCP NULL packets.
    tcp flags & (fin|syn|rst|psh|ack|urg) == 0x0 counter drop

    # Drop uncommon TCP MSS values.
    tcp flags syn tcp option maxseg size 1-535 counter drop
  }
}

- block INVALIDs in prerouting:

Example:

table inet mangle {

  # List of known ipv4 addresses to allow.
  set whitelist_v4 {
    type ipv4_addr
    flags interval
    auto-merge
    elements = { 185.220.100.0/22 }
  }

  # List of known ipv6 addresses to allow.
  set whitelist_v6 {
    type ipv6_addr
    flags interval
    auto-merge
    elements = { 2a0b:f4c2::/40 }
  }

  chain prerouting {
    type filter hook prerouting priority -150;

    # Allow loopback traffic.
    iifname lo accept

    # Allow whitelisted IPs
    ip saddr @whitelist_v4 counter accept
    ip6 saddr @whitelist_v6 counter accept

    # CT INVALID
    ct state invalid counter drop

    # TCP SYN (CT NEW)
    tcp flags & (fin|syn|rst|ack) != syn ct state new counter drop

  }
}

···

On Sunday, 13 September 2026 10:44 Toralf Förster via tor-relays wrote:

I eventually managed to have it [1] for nftables too and will continue
to maintain both variants.

--
╰_╯ Ciao Marco!

Debian GNU/Linux

It's free software and it gives you freedom!

I wrote it in a confusing way:

- Block crazy packets like this in line 172, in chain 'ingress' before conntrack:

Block crazy packets in chain 'ingress' before conntrack & defrag
and like this in line 172, in mangle (prerouting)

tcp flags & (syn|rst|ack|fin) != syn ct state new counter name "badflags" drop

# enum for the IPv4 protocol.

enum nf_ip_hook_priorities {
  NF_IP_PRI_FIRST = INT_MIN,
  NF_IP_PRI_RAW_BEFORE_DEFRAG = -450,
  NF_IP_PRI_CONNTRACK_DEFRAG = -400,
  NF_IP_PRI_RAW = -300,
  NF_IP_PRI_SELINUX_FIRST = -225,
  NF_IP_PRI_CONNTRACK = -200,
  NF_IP_PRI_MANGLE = -150,
  NF_IP_PRI_NAT_DST = -100,
  NF_IP_PRI_FILTER = 0,
  NF_IP_PRI_SECURITY = 50,
  NF_IP_PRI_NAT_SRC = 100,
  NF_IP_PRI_SELINUX_LAST = 225,
  NF_IP_PRI_CONNTRACK_HELPER = 300,
  NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX,
  NF_IP_PRI_LAST = INT_MAX,
};

···

--
╰_╯ Ciao Marco!

Debian GNU/Linux

It's free software and it gives you freedom!