Limit/prevent SSH brute force attempts

If you (have to) run a public available SSH server, you may have noticed already that there are a lot of brute force attacks trying to guess a user and password (have a look into /var/log/secure ). If you did it the correct way, you only allow public keys to authenticate of course. But maybe you can’t, because the client doesn’t support key authentication. Cisco routers/switches for example. Then (I personally do it on hosts which allow public keys only too) you can add some rules to your IPtables configuration (/etc/sysconfig/iptables on CentOS in this example):

### SSH - Do not block internal hosts/networks
-A INPUT -m state --state NEW -m tcp -p tcp --source 192.168.123.45 --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --source 192.168.234.0/24 --dport 22 -j ACCEPT
### SSH - Block brute force attempts
-A INPUT -m state --state NEW -p tcp --dport 22 -m recent --set --name ssh --rsource
-A INPUT -m state --state NEW -p tcp --dport 22 -m recent --update --seconds 3600 --hitcount 20 --rttl --name ssh --rsource -j REJECT
-A INPUT -m state --state NEW -p tcp --dport 22 -m recent --update --seconds 3600 --hitcount 19 --rttl --name ssh --rsource -j LOG --log-prefix "SSH brute force attempt: "
-A INPUT -m state --state NEW -p tcp --dport 22 -m recent --update --seconds 3600 --hitcount 19 --rttl --name ssh --rsource -j REJECT
-A INPUT -m state --state NEW -p tcp --dport 22 -m recent --update --seconds 60 --hitcount 5 --rttl --name ssh --rsource -j REJECT
### SSH - No limit reached
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
  • Lines 2 and 3 add some exceptions which should never be blocked
  • Line 5 marks the package with a name (Or more precise, the name of the list it saves the source IPs to)
  • Line 6 rejects all packages to port 22 if there were 20 or more attempts within an hour
  • Line 7 logs the package after 19 attempts and line 8 rejects it
  • Line 9 rejects the package if there were five or more attempts within a minute
  • Line 11 finally allows the package if it was not dropped before

This way you achieve this:

  • After the 4th attempt the request is rejected, but after a minute it will work again
  • On the 19th attempt it will be logged one time, all further attempts are rejected without logging each of them (within an hour)

Notes:
There is a default limit of 20 requests which are logged. You will get an error if you try to use a hitcount which is larger. You should be able to increase it by setting the modprobe option “options xt_recent ip_pkt_list_tot=100” (Never tired it myself because 20 is enough for me).

To flush the table you can execute “echo / > /proc/net/xt_recent/ssh”

This entry was posted in CentOS, Firewalls, Linux, Security and tagged , , , , . Bookmark the permalink.

One Response to Limit/prevent SSH brute force attempts

  1. Great post. Thanks. Can’t believe I had no idea you could do this with iptables…

Leave a Reply

Your email address will not be published. Required fields are marked *