This one-liner will reject new incoming ipv4 connections when more than 2 attempts per minute are made. It will also log a message about this:
firewall-cmd --add-rich-rule='rule family="ipv4" service name="ssh" log prefix="SSH Bruteforce:" level="warning" limit value="2/m" accept limit value="2/m"'
If you have both ipv4 and ipv6 configured you’ll probably want the more generic version:
firewall-cmd --add-rich-rule='rule service name="ssh" log prefix="SSH Bruteforce:" level="warning" limit value="2/m" accept limit value="2/m"'
Add the --permanent
option to make your rules permanent.
The rules above always log connections. I believe a more desirable behaviour would be to accept a certain number without logging, then log and drop excess connections. The following rules achieve that:-
firewall-cmd –zone=external –remove-service=”ssh”
firewall-cmd –zone=external –add-rich-rule=’rule priority=1001 service name=”ssh” accept limit value=”2/m”‘
firewall-cmd –zone=external –add-rich-rule=’rule priority=1002 service name=”ssh” log prefix=”FirewallD SSH bruteforce:” level=”warning” limit value=”1/m” drop’
Given that the above rules will block all connections from all IPs to port 22 once the threshold is reached, a better approach would be to change the SSH daemon’s port to something else (e.g. 3222) and apply the following rules:-
firewall-cmd –zone=external –add-rich-rule=’rule priority=1001 port protocol=”tcp” port=”3222″ accept limit value=”2/m”‘
firewall-cmd –zone=external –add-rich-rule=’rule priority=1002 port protocol=”tcp” port=”3222″ log prefix=”FirewallD SSH bruteforce:” level=”warning” limit value=”1/m” drop’
This would still block all IPs trying to access the port, but should be better since the number of attackers attacking a non-default port is probably less.
The best solution would be something like fail2ban, which will block specific hosts and whatnot.