There is a new extension nft_connlimit that was added since Linux kernel 4.18, providing a ct count
expression.
For this case, the equivalent rules (from scratch) would be:
nft flush ruleset
nft add table ip filter
nft add chain ip filter input '{ type filter hook input priority 0; }'
nft add rule ip filter input tcp dport 22 ct count 10 counter accept
# nft add rule ip filter input tcp dport 22 counter reject with tcp reset
Some remarks:
As usual counter
is optional and is used to get a counter with nft list ruleset
to know how many times the rule triggered.
Replacing above all occurences of ip
with ip6
will get the equivalent for IPv6. Now what's more interesting is using inet
to get a combined count of IPv4 and IPv6 SSH connections together since they are accounted together by conntrack.
Kernels between 4.19.0 and 4.19.9 must be avoided, because using this feature will likely crash the host. (Upcoming) kernel 4.20 and kernel 4.19.10 include several patches related to conncount, fixing crashes and wrong count. Status unknown for kernel 4.18.x.
UPDATE: limit per network instead of just per IP, equivalent to iptables' --connlimit-mask
Rereading scarce documentation from the initial patch in netfilter-devel mailing list, ct count
isn't limited to be used just standalone (or would be limited to the example above). It can be used within a meter
expression/list for any more complex usage.
Should one want to reject connections to port 2222 (where some process is listening) above 3 connection counts per any random /24 network source IP, this rule should be used (as of nft 0.9.0 / kernel 4.19.10):
nft add rule ip filter input tcp dport 2222 meter test-2222-count-meter '{ ip saddr & 255.255.255.0 ct count over 3 }' counter reject with tcp reset
This will create a meter list named test-2222-count-meter
which will dynamically add the relevant "map" data (for every different /24 network having matched a connection). I'm not sure if stale data (ie /24 networks not having any connection anymore) is ever removed via garbage collection or not.
The meter's contents can be listed (it won't show the count reached, just the dynamically added "maps" when new networks are seen). Eg after some connections from 10.0.3.1
, 10.0.3.66
, 10.0.4.5
and 172.31.4.5
:
# nft list meter ip filter test-2222-count-meter
table ip filter {
meter test-2222-count-meter {
type ipv4_addr
size 65535
elements = { 10.0.3.0 : ct count over 3 , 10.0.4.0 : ct count over 3 , 172.31.4.0 : ct count over 3 }
}
}