Bruteforce attacks


If you're allowing ssh logins from anywhere on the internet it's inevitable that someone, or a script, will eventually try to find a username/password combination to log in. A quick look at the auth log shows


Apr 7 19:42:00 220960 sshd[66725]: Invalid user webmaster from 86.146.130.236
Apr 7 19:42:00 220960 sshd[66725]: Failed password for invalid user webmaster from 86.146.130.236 port 57442 ssh2
Apr 7 19:42:01 220960 sshd[66734]: Invalid user webmaster from 86.146.130.236
Apr 7 19:42:01 220960 sshd[66734]: Failed password for invalid user webmaster from 86.146.130.236 port 57449 ssh2


In our previous pf rules, the range of IPs from which ssh access is possible was retricted to my ISP's range - this is probably still several hundred thousand IP addresses!
A variety of scripts have been written to scan logs for brute force attacks and perhaps also then block the offending IP address. However with pf, blocking brute force attacks is extremely simple.
First define the following table in /etc/pf.rules


table <bruteforce> persist


and we'll add the following rules


block in quick on $IF from <bruteforce> to any
pass in on $IF inet proto tcp from $TRUSTED to $SERVER port ssh flags S/SA keep state \
(max-src-conn-rate 1/10, overload <bruteforce> flush global)


max-src-conn-rate is the rate of new connections allowed from one IP address, and in the example here I'm allowing 1 connection per 10 seconds.
overload <bruteforce> means that any IP which exceeds these limits is added to the table bruteforce. Our rule set blocks all traffic from IP addresses in the bruteforce table.
flush global says that when an IP reaches the limit, all that IP's connections will be terminated.
Reload our conf and we're done.