IPTables Against SSH Dictionary Attacks

Like everybody who has a Linux server running an SSH daemon connected to the Internet, I regularly get attacked by people (well, botnets probably) trying to do a brute-force attack against the server. Such attempts can take many hours, during which they simply try many thousands of possible username/password combinations.

As long as you have your SSH server configured properly, the most important thing being to only allow SSH access to accounts which actually need it, this is more an annoyance than a problem. Nonetheless, it is an annoyance, if only because of all the crap in your logfiles.

There are many ways to detect and block such attacks. sshdfilter works well, and a good detailed overview of the various options can be found here. One that particularly appealed to me, however, was a very simple netfilter-based technique consisting of only two lines of iptables code. It uses the recent netfilter extension, and the idea of using it to combat SSH attacks was apparently first conceived by Andrew Pollock.

Here’s my version:

iptables -A INPUT -p tcp --dport ssh -m state --state NEW \
         -m recent --set --name SSH -j ACCEPT
iptables -A INPUT -p tcp --dport ssh -m recent --update \
         --seconds 600 --hitcount 6 --rttl --name SSH -j DROP

This will blacklist a given IP address as soon as six TCP connections to the SSH port are detected from that address within ten minutes, and then the blacklist will remain in effect until no further connection attempts have been made from that address during the past ten minutes. This is the most basic version: it does not support whitelisting and there’s no logging, but it works very well at what it does. As I can see from my logs, all crack attempts are indeed broken off after the first six attempts, and they generally don’t come back.

This is just one of the many reasons why Netfilter/IPTables is such a great tool. Sure, it’s a bit intimidating at first, but once you understand the basics, you can fine-tune your server’s routing and firewalling configuration to an almost limitless degree.

What I’m still looking for, however, is a way to control the ‘detection period’ and the ‘blacklist period’ separately. For example, if six SSH connections are made from a given address within four minutes, that address is blacklisted for the next twelve hours. Anybody know of a good way to do that?