dischord.org » Stopping brute force SSH attacks with pf
pf, which originated from the OpenBSD project, is easily one of the most elegant firewalling solutions I’ve ever come across. Check this example out. I was getting pretty tired of all the SSH dictionary-type attacks on our new box - a problem compounded by the fact that we’re running various jails and so multiple instances of sshd - and so I looked for an easy way to stop this. The obvious solution is to move sshd off port 22, but I couldn’t be bothered with the user education for this to happen. Another option is to use something like DenyHosts, but as that has its own history of security invulnerabilities I decided against that as well.
Enter pf, and a trivial rule such as this:
pass in on $ext_if inet proto tcp from any to { $fork, <jails> } port ssh \
flags S/SA keep state (max-src-conn 15, max-src-conn-rate 5/40, \
overload <bruteforce> flush global)
So we have a table called ‘jails’ which contains a list of IP addresses for each hosted jail, and a persistent tabled called ‘bruteforce’. SSH to port 22 is allowed, however if there are more than 15 connection from one source, or if the connection rate exceeds 5 every 40 seconds, they’re stuck into the ‘bruteforce’ table. And right at the top, we have:
block quick from <bruteforce>
So they’re instantly blocked and tracked for future reference. A few days later…..
$ sudo pfctl -t bruteforce -Tshow | wc -l
130
So 130 IP addresses caught and tracked. Nice.