Dynamically removing a known nft rule

By chimo on (updated on )

I have the creation and configuration of my Incus containers automated. This includes configuring nftables. On Alpine Linux, this typically just means adding a rule to allow traffic from an IP/range on a specific port. On Archlinux, however, a built-in rule was giving me trouble so I needed to get rid of it programatically.

The line I want to remove is:

meta pkttype host limit rate 5/second burst 5 packets counter packets 0 bytes 0 reject with icmpx admin-prohib

As far as I know, to delete a rule with nft, the command is:

chimo@xps:~$ doas nft delete inet filter input handle <handle>

You can find the “handle” part with:

chimo@xps:~$ nft -a list table inet filter
table inet filter { # handle 4
  chain input { # handle 1
    type filter hook input priority filter; policy drop;
    ct state invalid drop comment "early drop of invalid connections" # handle 3
    ct state { established, related } accept comment "allow tracked connections" # handle 5
    iif "lo" accept comment "allow from loopback" # handle 6
    ip protocol icmp accept comment "allow icmp" # handle 7
    meta l4proto ipv6-icmp accept comment "allow icmp v6" # handle 8
    tcp dport 22 accept comment "allow sshd" # handle 9
    meta pkttype host limit rate 5/second burst 5 packets counter packets 0 bytes 0 reject with icmpx admin-prohibited # handle 10
    counter packets 0 bytes 0 # handle 11
  }

  chain forward { # handle 2
    type filter hook forward priority filter; policy drop;
  }
}

My quickfix for my particular situation ended up being:

#!/bin/sh -eu

handle=$(nft -a list table inet filter | \
                grep 'host limit rate' | \
                grep -oE 'handle [0-9]+' | \
                grep -oE '[0-9]+'
        )

nft delete rule inet filter input handle "${handle}"

There are probably more elegant ways to do this, and I should add error handling, but in a pinch it did the trick.