In order to protect your Relay Node(s) from a novel “DoS/Syn” attack, Michael Fazio created iptables entry which restricts connections to a given destination port to 5 connections from the same IP.
I am not sure you will get that much benefit from trying to connection limit based on source IP address. The problem is that if someone wants to DoS attack you then they can easily use one of their “bot farms” to hit your server from hundreds of different source IP addresses. Under such an attack, this 5 connection limit per source address iptables rule will be ineffective because if the attacker has 100 bots then they can still open up 500 connections to your relay. And 1000 bots can open 5000 connections.
I used to have limits per IP address for various things in my firewalls but I find that even when people are trying to scan for open ports they tend to use bot farms to scan using multiple source IP addresses. Hackers know that admins try to firewall them using rules like the one suggested so they deliberately try not to trigger such common defences. Consequently the added complexity in your firewall is often not worth it.
But, I do find similar nftables features useful to limit filling your logs with stuff you are not that interested in. For example, nftables makes it possible to use sets and you can use concatenations to match multiple criteria. This allows things to be simplified quite a bit. For example, I do the following sort of thing to limit my logs:
set tcpudp_dropped {
type inet_proto . ipv4_addr . inet_service
size 65535
flags dynamic,timeout
}
set icmp_dropped {
type ipv4_addr
size 65535
flags dynamic,timeout
}
chain tcpudp_logdrop {
ip protocol . ip saddr . th dport != @tcpudp_dropped log prefix "DROP: " flags all
update @tcpudp_dropped { ip protocol . ip saddr . th dport timeout 10s }
drop
}
chain icmp_logdrop {
ip saddr != @icmp_dropped log prefix "DROP: " flags all
update @icmp_dropped { ip saddr timeout 10s }
drop
}
chain logdrop {
ip protocol vmap { icmp : jump icmp_logdrop, tcp : jump tcpudp_logdrop, udp : jump tcpudp_logdrop }
jump other_logdrop
}
chain input_filter {
type filter hook input priority filter; policy drop;
iif "lo" accept
... snip - various filter rules ...
jump logdrop
}
At the end of the filter chain (I named it ‘input_filter’), just before it applies the default policy of drop, it jumps to the logdrop chain. The logdrop chain then maps (vmap) on ip protocol to fan out jumping to other chains depending on the protocol (icmp, tcp, udp). In the case of an icmp packet, it logs the packet (with flags all) if the ip saddr was not already in the icmp_dropped set, and updates the set with the ip saddr with a timeout of 10 seconds, then drops the icmp packet. (My router doesn’t respond to icmp packets including pings from unknowns.)
That allows me to just add “jump logdrop” anywhere in my input and forward chains whenever I want to drop a packet. In doing so, I stop my logs from filling up by logging only the first such icmp packet every 10 seconds per each source IP address. Or in the case of tcp/udp packets I want to drop, I log only the first packet having the same combination of protocol (tcp/udp), saddr, and port.
Hopefully that gives you some ideas if you are keen to write your firewall using the latest firewalling tool on linux (nftables).