-- sshdfilter V1.4.5 --
ssh brute force attack blocker


sshdfilter blocks the frequent brute force attacks on ssh daemons, it does this by directly reading the sshd logging output and generating iptables rules, the process can be quick enough to block an attack before they get a chance to enter any password at all.

sshdfilter starts sshd itself, having started sshd with the -e and -D options. This means it can see events as they happen. sshdfilter then looks for lines of the form:
Did not receive identification string from x.x.x.x
Illegal user x from x.x.x.x
Failed password for illegal user x from x.x.x.x port x ssh2
Failed password for x from x.x.x.x port x ssh2

The former three instantly trigger sshdfilter into creating iptables rules which block all ssh access from that IP. The latter failure is given a few chances before it too is blocked. These are in fact example rules, the exact wording varies between Linux distributions, so sshdfilter exists as a base program and groups of patterns for each distribution.

All new rules are inserted into a custom chain, and to prevent the chain from becoming overloaded with old rules, rules over a week old are deleted.

Taking some statistics from my logs before sshdfilter was implemented, the longest attempt from a single IP was half an hour long, trying around 1 username/password pair per second. Over 26 days there were attacks from 42 unique IPs, none of them ever came back after the attempt. Picking the oldest 10 of these attacks, they had 347, 306, 115, 115, 127, 18, 554, 107, 9, 52 failed(!) password attempts. Of these 1750 attempts, 720 were for root - making a good case for blocking password authentication of the root account.

With sshdfilter installed, taking each attack on a case by case basis:
347 attempts becomes 0 attempts - first attemped guess was for a non-existant user, so was instantly blocked.
306 attempts becomes 0 attempts - same reason, non-existant user.
115 attempts becomes 1 attempt - first guess was for root and is allowed a default of 3 chances, the second guess was for a non-existant user and so was blocked anyway.
115 attempts becomes 1 attempt - same as previous.
127 attempts becomes 3 attempts - many initial guesses for root account, so sshdfilter blocks after the first 3 failed attempts.
18 attempts becomes 0 attempts - first attempted guess was for a non-existant user, so was blocked instantly.
554 attempts becomes 3 attempts - many initial guesses for root accont, so sshdfilter blocks after the first 3 failed attempts.
107 attempts becomes 1 attempt - first guess was for a valid user (nobody), second guess was for a non-existant user so was blocked.
9 attempts becomes 0 attempts - first guess was for a non-existant user so was blocked instantly.
52 attempts becomes 3 attempts - many initial guesses for root accont, so sshdfilter blocks after the first 3 failed attempts.

Summerising, of these 10 sample attacks, 1750 attempts, 720 were for root, 1013 were for illegal accounts, the rest were for existing accounts. Using only user name gusses alone, sshdfilter would have blocked 1729 of these. In fact, until the authors of the brute force attacks improve their code and send an ssh id string, sshdfilter would actually have blocked 1744 attempts, allowing only 6 guesses of the root account over an average of 6 days. Had password based root access been banned, even these six would have been futile.

Right now sshdfilter works with Debian 3.1, Redhat 7.3 to 9.0, Fedora Core 2-4, CentOS, Suse 10.0 RC 1, RedHat Enterprise Linux 4 and gentoo, Mandriva, and the many derivatives. Each distribution uses different logging messages, so sshdfilter needs a pattern list for the target system. Patterns are supplied for RedHat 7.3 and 9.0 systems, RedHat Fedora Core 3 systems, Suse 10.0 RC 1 and Debian 3.1 (sarge, stable) systems, the other distributions use patterns based on these 4. There is also support for Dropbear, a light weight ssh server.


The really old stable version can be found here(V1.3.5).

The stable version can be found here(V1.4.5).

The web page for the testing version (V1.5.x) can be found here - if the previous versions aren't flexible enough for you, this version will be.

sshdfilter has been ported to Dropbear, and is available here(V1.4.3.2-dropbear). Dropbear is a light weight sshd server.

For a comparison, the changlog is below, and continues into 1.5.x here.

Installation (for <=sshdfilter 1.4.x)

This was written with common Linux distributions in mind, and so expects to find perl, the iptables command and support syslog style logging.

Add iptables chain with (/etc/sysconfig/iptables style):
:SSHD - [0:0]
or bash:
iptables -N SSHD

Add a jump to SSHD rule with something like:
-A INPUT -p tcp -m tcp --dport 22 -j SSHD
or bash:
iptables -I INPUT -p tcp -m tcp --dport 22 -j SSHD

This is only an example, I've no idea how you set up your iptables. Generally you'll have a line that ACCEPTS ssh(port 22), and the above should go on the line before. Notice I've used -I on the second example, which adds to the start of the chain instead of the end. The -I has more chance of working when added to a running system. The command:
iptables -L INPUT -vn
should show something like:
Chain INPUT (policy ACCEPT 22M packets, 1901M bytes)
pkts bytes target prot opt in out source destination
.... various site specific rules deleted
366 22424 SSHD tcp -- eth1 * tcp dpt:22
138 9940 ACCEPT tcp -- eth1 * tcp dpt:22
.... various site specific rules deleted
47996 3742K DROP all -- eth1 * state INVALID,NEW
Where the last rule blocks all new connections that haven't been ACCEPTed in the past, ie, a statefull rule.

This is only an example, I've no idea how you set up your iptables. Generally you'll have a line that ACCEPTS ssh(port 22), and the above should go on the line before. Some systems (notably Suse) use custom firewall scripts, see README.suse for contributed instructions.

You will also need to modify your startup script so that sshdfilter is run instead of sshd. sshdfilter will then itself run sshd. sshdfilter V1.4.x will daemonise, so you can run sshdfilter like you'ed run sshd. A sample RedHat style startup script is in the tar file, note only one line has changed from the distribution supplied default.

sshd log messages vary across distributions, so you need to install the correct sshdfilter executable for your sshd. Several are provided, supporting Debian 3.1, Redhat 7.3 to 9.0, Fedora Core 2-4, CentOS, Suse 10.0 RC 1, RedHat Enterprise Linux 4, and the many other distros based on these. If your log messages are too different you can also add your own using those provided as an example.

Copy etc/sshdfilterrc to /etc/ and edit to suit your requirements. You may want to uncomment and properly set $interface, which allows for only blocking (say) the external interface - so even triggering sshdfilter into blocking won't actually do anything if you are ssh'ing from the inside/via VPN.


sshdfilter comes with a LogWatch script that understands sshdfilter output. You need a recent (6.1.x) version of LogWatch to use these LogWatch scripts. sshd logging works as it used to, sshdfilter always logs sshd output regardless of it triggering sshdfilter to do some action. The LogWatch scripts consist of two files, you also need to add 'sshdfilt' to /etc/log.d/conf/services/secure.conf (or similar, try 'grep "sshd " /etc/log.d/conf' to find mentions of sshd, sshdfilt should be there too), to tell the 'secure' parser script about sshdfilter - so the 'secure' parser can ignore sshdfilter messages.

Note the scripts expect to find LogWatch version 6.1.x, anything else and you will have to modify the script. That includes later versions.

ToDo (all but Solaris support now implemented in 1.5.x)

1. Per user tunable maxchances and maxblocktime, using regular expressions.

2. Add a thanks section somewhere, people deserve some credit for their patches and bug reports

3. Be more tolerant of failures for standard users, maybe block for less time, or allow more guesses

4. Related to 2., allow for safe nets, so many failures on these nets don't ever lead to automatic blocking. At the moment, consider this a misfeature, and would be better implemented with iptables rules provides exceptions. -- decided this would be a misfeature, would be better if a good nets was placed in iptables just before jumping to the sshd chain.

5. Add support for Solaris. William L. Sebok has sent large patches against 1.4.4, but I'd rather build on 1.5.x


Some common questions and other bits of information can be found here in the FAQ.

Change log

V1.0 Initial test release, trialed on RH7.3 and RH9 machines.

V1.1 Tested on a FedoraCore3 system and installed by somebody other than me. Some bugs found, namely, path to sshd and the change in wording of sshd log messages (Illegal/Invalid).

V1.2 5/6/2005 Added subprocess so sshd could have its own log entry, this avoids confusing LogWatch type programs, so only the sshdfilter output needs a new log parser. This is also the first web release.

V1.3 9/6/2005 (Testing) Added config file and easier support for different logging messages, as so many distros like to use different messages for the same thing.

V1.3.1 11/6/2005 Fixed configuration file bug that skipped maxblocktime. Added logwatch support (needs a fairly recent version of LogWatch). Renamed directories and tar.gz to contain a version number.

V1.3.2 15/6/2005 Added a version number to the startup message. A missing config file is now non-fatal.

V1.3.3 18/6/2005
1. Better shutdown. sshdfilter now properly quits even when sshd has children. Acts on the 'sshd received...' message.
2. Block time reduced to 3 days, might go lower still.
3. LogWatch scripts syncronised to this version.
4. Number of attempts($maxchances) is now (interally anyway) a distribution specific parameter.
5. Modified INSTALL and some comments.
6. SSHD chain rules are now flushed at startup, might as well as nothing else will.
7. Gave the debug messages a consistent format.

V1.3.4 17/7/2005
1. Install script has been written, needs more testing but could work for you.
2. Check for SSHD redirect broke when the redirect was after the SSHD chain.
3. Changed wording of config file to better explain repurgetime.
4. Changed warning text of iptables checker, warns that sshdfilter prob won't work.
5. Fixed a DoS and remote root exploit caused by bad assumptions during log parsing, namely assuming user names couldn't contain a space. Thanks to Aaron Hopkins for pointing this out. Upgrading from all versions is recommended.

1. Settled on a license, now GPL.

V1.3.5 24/9/2005
1. Support IPv6 addresses. Needed for some recent distributions, such as Debian 3.1 Sarge.

V1.4.0 20/10/2005
1. Support for Suse 10.0 RC 1
2. Support for CentOS
3. Red Hat Enterprise Linux ES release 4
4. Daemonise, like sshd does. Now better replaces sshd in the startup scripts.
5. select() now used to read sshd output, making repurgetime much more responsive when a small value is given.
6. Email someone on block events.
7. More support for IP6 and conversion to IP4.

V1.4.1 9/11/2005
1. Fix bug/typo in IPv6 to IPv4 conversion. Conversion was never done.

1. Changed website to say more about choosing an sshdfilter executable for the target system.

V1.4.2 10/12/2005
1. Support for RedHat Fedora Core 2.
2. Support for RedHat Fedora Core 4 (was already supported, but nothing actually said so).

V1.4.3 10/2/2006
1. $interface has been replaced by $iptablesoptions, making it easier to specify the port, and any other options you might want to specify, such as -j REJECT.
2. Spawn another process when sending email, so a hanging email command won't delay sshdfilter.
3. Check for result code from system() calls when adding block rules.
4. The SSHD chain name is now a config option, so multiple instances of sshdfilter can have their own chains.
5. Support for multiple confirugation files has been added.
5. Support Gentoo, which has been reported to work with the Suse patterns.
6. Support Debian sid, based around Debian 3.1 sarge.
7. Improve LogWatch installer for Fedora Core 4, base dir now /etc/logwatch.
8. Improve LogWatch script compatibility with other versions of LogWatch.
9. Written man pages for sshdfilter and sshdfilterrc.

V1.4.3.1 20/2/2006
1. Fixed typo in error logger.

V1.4.3.2 22/2/2006 (thanks to andre sebastian liebe, master-andre at gmx de)
1. Table name SSHD was still hardcoded in the iptables setup check.
2. Removed 2>/dev/null from same check, could help inform user of problems with the iptables command.

V1.4.4 12/6/2006 (thanks to Torbjorn Tyridal, torbjorn at tyridal no; Sheldon Whynott, labatman at 2keys ca; Soren Kroer, spookyisback at hotmail com; Christopher R. Curzio, accipiter at accipiter org)
1. Support for CentOS 4.3.
2. Support for Slackware.
3. Support for Debian sid.
4. Fixed bug loading config, SSHDFILTERRC was ignored.
5. Fixed man page installation in install.pl.

V1.4.5 17/11/2006
1. Support for Mandriva, thanks to Andrzej Kaczmarczyk.
2. More support for Suse, better handling Suse custom firewall scripts. Thanks to Dougie Lawson and Chris Sims.
3. Fixed bug in configuration error reporting, line numbers always 0, thanks to William L. Sebok.

V1.5.0 12/6/2006
1. Rewrote the configuration parser and the pattern matching engine, this should provide all the flexibility you could ever want.
2. sshdfilter can now read sshd messages from either sshd -eD(used by all previous versions of sshdfilter), or via a named pipe maintained by syslog.

V1.5.x changelog now here.


Written by Greg: greg at csc liv ac uk. Would welcome any comments.
LogWatch script written by Tommo: sshdfilter at gmail com.


This software is released under the terms of the GNU GPL.