nftables rate limiting per multiple seconds

3k views Asked by At

I'm trying to convert some iptables rules to nftables I want to make a rule that blocks a connection if there are more than 4 attempts in a 30 seconds time span

My original iptables rules are:

iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 30 --hitcount 4 --rttl --name SSH -j DROP

How can I do the same (or equivelent) in nftables?

2

There are 2 answers

0
Lobz On

As far as I understand the iptables recent module does not have an equivalent in nftables, however, you should be able to achieve similar functionality using meters.

nft add rule ip filter INPUT tcp dport 22 ct state new meter SSHban { ip saddr and 255.255.255.255 limit rate over 8/minute burst 4 packets } counter drop

Documented here: https://wiki.nftables.org/wiki-nftables/index.php/Meters

0
Chen Deng-Ta On

I try months, can not find an exact match. But the I have a workaround.

sshPort=2222
nft add table ip sshGuard
nft add chain ip sshGuard input { type filter hook input priority 0 \; }
nft add set ip sshGuard denylist { type ipv4_addr \; flags dynamic, timeout \; timeout 5m \; }
nft add set ip sshGuard sshlist { type ipv4_addr \; flags dynamic, timeout \; timeout 5m \; }
nft add rule ip sshGuard input ct state established,related accept
nft add rule ip sshGuard input tcp dport $sshPort ct state new ip saddr @denylist reject
nft add rule ip sshGuard input tcp dport $sshPort ct state new ip saddr @sshlist add @denylist { ip saddr } accept
nft add rule ip sshGuard input tcp dport $sshPort ct state new limit rate over 2/minute burst 3 packets add @sshlist { ip saddr } counter accept
nft list table ip sshGuard

For a fresh state, around 5 connections will be accepted for any new IP. If the limit rate is hit, a new IP (not in sshlist) has 2 chances. For any IP in sshlist, only one chance left. And for any IP in denylist, any new connection will be rejected, until it is deleted from the denylist by its 5 minute timeout.