I want to create a dynamic blacklist with nftables. Under version 0.8.3 on the embedded device I create a ruleset looks like this with nft list ruleset:
table inet filter {
set blackhole {
type ipv4_addr
size 65536
flags timeout
}
chain input {
type filter hook input priority 0; policy drop;
ct state invalid drop
ct state established,related accept
iif "lo" accept
ip6 nexthdr 58 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, echo-reply, mld-listener-query, mld-listener-report, mld-listener-done, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } accept
ip protocol icmp icmp type { echo-reply, destination-unreachable, echo-request, router-advertisement, router-solicitation, time-exceeded, parameter-problem } accept
ip saddr @blackhole counter packets 0 bytes 0 drop
tcp flags syn tcp dport ssh meter flood { ip saddr timeout 1m limit rate over 10/second burst 5 packets} set add ip saddr timeout 1m @blackhole drop
tcp dport ssh accept
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
For me this is only a temporary solution. I want to use the example from the official manpage for dynamic blacklisting. If I use the offical example from the manpage my nftables file looks like this:
table inet filter {
set blackhole{
type ipv4_addr
flags timeout
size 65536
}
chain input {
type filter hook input priority 0; policy drop;
# drop invalid connections
ct state invalid drop
# accept traffic originating from us
ct state established,related accept
# accept any localhost traffic
iif lo accept
# accept ICMP
ip6 nexthdr 58 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, echo-reply, mld-listener-query, mld-listener-report, mld-listener-done, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } accept
ip protocol icmp icmp type { destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem, echo-request, echo-reply } accept
# accept SSH (port 22)
ip saddr @blackhole counter drop
tcp flags syn tcp dport ssh meter flood { ip saddr timeout 10s limit rate over 10/second} add @blackhole { ip saddr timeout 1m } drop
tcp dport 22 accept
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
But when I load this nftables file on version 0.8.3 with nft -f myfile I get this error:
Error: syntax error, unexpected add, expecting newline or semicolon
tcp flags syn tcp dport ssh meter flood { ip saddr timeout 10s limit rate over 10/second} add @blackhole { ip saddr timeout 1m } drop
I don't know why this is the case, but according to the wiki it should work from version 0.8.1 and kernel 4.3.
I have version 0.8.3 and kernel 4.19.94.
I have tested under Debian Buster the ruleset from the official manpage with version 0.9.0. The ruleset from the manpage works fine with Debian, but the ip is blocked only once.
With this example I want to create a firewall rule which blocks the ip adress on ssh port if an brute force attack is started to my device. But I want to block the ip e.g for 5 minutes. After that time it should be possible to connect again to the device from the attackers ip. If he do brute force again it should be block the ip again for 5 minutes and so on. I want to avoid to use another software for my embedded device like sshguard or fail2ban if it is possible with nftables.
I hope anyone can help me. Thanks!
hydra -l <username> -P </path/to/passwordlist.txt> -I -t 6 ssh://<ip-address>