Diary of a geek

February 2005
Mon Tue Wed Thu Fri Sat Sun

Andrew Pollock


Other people's blogs


RSS feed

Contact me

JavaScript required

Wednesday, 16 February 2005

Mitigating against SSH brute force attacks using Netfilter and the recent module

As I mentioned previously, I recently discovered the wonders of Netfilter's recent module, and have decided to try and employ it to ward off the evil script kiddies and their brute force SSH scripts.

As I like to be able to SSH to my server from where ever I happen to be, and I won't necessarily have the infrastructure to use public key based authentication, I thought I'd see how a bit of selective packet filtering would go.

I'm using:

iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -m recent --update --seconds 60 --hitcount 4 --rttl --name SSH -j LOG --log-prefix "SSH_brute_force "
iptables -A INPUT -p tcp --dport 22 -m recent --update --seconds 60 --hitcount 4 --rttl --name SSH -j DROP

This will allow three port 22 connections from any given IP address within a 60 second period, and require 60 seconds of no subsequent connection attempts before it will resume allowing connections again. The --rttl option also takes into account the TTL of the datagram when matching packets, so as to endeavour to mitigate against spoofed source addresses.

As an additional nicety, I could refine this to use a custom chain and a whitelist that exited the chain for source IPs that were trusted.

I'm going to run this ruleset on my server for a while and see if I

  1. don't lock myself out
  2. make a dent in SSH brute force attacks


After much discussion with Juergen Kreileder, this ruleset would appear to be slightly better:

iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j SSH_WHITELIST
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 --rttl --name SSH -j ULOG --ulog-prefix SSH_brute_force
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 --rttl --name SSH -j DROP

This has the (arguably) added benefit of not hosing any established SSH connections from the host that has made too many SSH connections in a short period of time, and allows for whitelisting.


I've had a few people email me and ask about the whitelisting part, which I didn't do a terribly good job of explaining. I should have said that you need to create a custom chain first:


and then add whitelisted hosts to it in a manner like this:

iptables -A SSH_WHITELIST -s $TRUSTED_HOST -m recent --remove --name SSH -j ACCEPT

this clears the whitelisted host out of the recently seen table, and because is has an ACCEPT jump target, should stop further processing anyway.

[14:32] [tech/security] [permalink]