-- sshdfilter V1.5.7 --
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 (or syslog output) and generating iptables (or ipfw) rules, the process can be quick enough to block an attack before they get a chance to enter any password at all. The blocking policy is defined by a list of blockrules largely by user name or by the type of user name. There are two install routes, the original style sshdfilter starts sshd itself, having started sshd with the -e and -D options. The newer style uses a syslog configuration line that writes sshd messages to a dedicated named pipe, normally /var/run/sshd.fifo. Regardless, this means sshdfilter can see events as they happen and act on them as they happen. sshdfilter then looks for lines something like:

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

When sshd produces any of these messages (or similar, depending on your version of sshd), the response of sshdfilter is defined by the configuration file /etc/sshdfilterrc. The default configuration file defines the first message as in instant block event that will install an iptables rule blocking that IP. The other lines are given 3 chances (ie. this chance and two more) before an iptables DROP rule is generated and their IP is blocked.

These are example messages, the exact wording varies between Linux distributions, so the provided distribution configuration file sshdfilterrc contains default policies and many variants of sshd messages (also provided in patterns/), the combination of these should cover the vast majority of sshd daemons found in Linux distributions. IP blocks are added into a custom iptables chain, and to prevent the chain from becoming overloaded with old rules, old rules are deleted. IP block duration is also specified in the configuration file.

Testing the effectiveness of sshdfilter in May 2010, a test machine without sshdfilter was setup on a consumer broadband connection with a dynamic IP, the sshd logs covered 16 days. The largest number of attacks from a single IP was 18402 attacks over 18 hours 12 minutes, equating to an attack every 3.6 seconds. The fastest rate of attack from a single IP was 2232 attacks in 11.5 minutes, equating to 3.2 attacks per second. The longest attack from a single IP was 5.5 days, in which 21 attempts at the password were made, in this case the attacker came back 5.5 days later. Plotting duration vs number of attacks shows 3.6 seconds per attack is the most common attack rate, these other examples were outliers. The graph also shows the most common attack duration is around 20 minutes. Over 16 days there were attacks from 62 unique IPs. Picking the oldest 10 of these attacks, they were 903, 57, 15, 212, 64, 74, 8, 18977, 9 and 206 failed password attempts. Of these 20525 attempts, 595 were for root. This plot shows the actual spread of attacks per source IP.

Had sshdfilter been installed with the default blocking policy, taking each attack on a case by case basis (grouped to make the repeats more identifiable):
903 attempts becomes 0 attempts - attacker first tests sshd port, so was instantly blocked.
57 attempts becomes 0 attempts - instantly blocked for the same reason.
15 attempts becomes 0 attempts - instantly blocked for the same reason.
212 attempts becomes 0 attempts - instantly blocked for the same reason.
18977 attempts becomes 0 attempts - instantly blocked for the same reason.
206 attempts becomes 0 attempts - instantly blocked for the same reason.
64 attempts becomes 3 attempts - many guesses for a non-existant user, so sshdfilter blocks after the first 3 failed attempts.
74 attempts becomes 3 attempts - many initial guesses for root accont, so sshdfilter blocks after the first 3 failed attempts.
8 attempts becomes 3 attempts - same as previous, sshdfilter blocks after the first 3 failed attempts.
9 attempts becomes 3 attempts - guess for non-existant user and then root, so sshdfilter blocks after the first 3 failed attempts.

Summerising, using only user name gusses alone, sshdfilter would have blocked 20495 of these attempts, allowing only 30 attempts. Until the authors of the brute force attacks improve their code and send an ssh id string, sshdfilter would actually have blocked 20513 attempts, allowing only 12 guesses at a password over 16 days, mostly for the root account. Had password based root access been banned, even these would have been futile. These 10 examples also represent the fastest and slowest attack identification speeds. It is also possible to identify attacks after 1 to 2 attempts, simply because the attacker used a common user name. A list of popular user names appears in /etc/sshdfilterrc.

sshdfilter was originally written to work with Debian 3.1, Redhat 7.3 to 9.0, Fedora Core 2-4, CentOS, Suse 10.0 RC 1, RedHat Enterprise Linux 4, Slackware and gentoo. More distributions have been added, derivatives have since appeared and the old distributions have been updated. The latest (1.5.7, testing) version of sshdfilter brings together all distribution specefic patterns in one configuration file, automatically including most of the wide variation in sshd log messages that are available today. If your system isn't listed, it will still most likely work. It also supports Mac OS X, though the specially written package is recommended as that includes an installer.


Stable version, also with with ipfw support can be found here(V1.5.5).
Testing version, with multi-line pattern matching can be found here(V1.5.7).
A pre-configured Mac OS X package can be found offsite here.
Older versions can be found at on their own page here.


sshdfilter was written with common Linux distributions in mind, and so expects to find perl, the iptables command (or ipfw command) and support syslog style logging. For the details, see INSTALL and INSTALL.ipfw.


1. Write a corresponding (for v1.5.x) LogWatch script.
2. Update automated install.pl script, which is now very old compared to the distribution it is likely to be used on.
3. Different method of getting the sshd pid when running mulitple sshds with install route 2. Current method is impractical.


Some common questions and other bits of information can be found here in the FAQ, which is aimed at pre 1.5 but some issues, like the problems created by firewall generators will still apply.

Change log

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

V1.2.x 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.x 9/6/2005 Added config file and easier support for different logging messages, as so many distros like to use different messages for the same thing.

V1.4.x 20/10/2005 Daemonise and use select()

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.1 6/7/2006 (Thanks to Tommo)
1. Config file contained a spurious line, and spurious sshd patterns.
2. Source code wrongly refered to /etc/sshdfilterrc15.

V1.5.2 17/11/2006
1. Fixed bug that made sshdiflter quit if reading from a pipe and syslog restarted. The pipe is now reopened.
2. Fixed bug in sshdfilter startup script (route 2 style), 'restart'/'stop' was broken, killall also killed the startup script because it had the same name.
3. Fixed a few typos.
4. Wrote install scripts for both sshd wrapper and standalone installation options.

V1.5.3 14/1/2007
1. Added hostname lookup for messages. Some PAM based systems shows source hostnames, never source IP.
2. Added hostname based pattern for Debian 3.1 system.
3. Added config error checking, tells the user if they forgot to include machine specific patterns.
4. Cleaned up code that reopens the named pipe when syslog restarts.
5. Removed many errors from the alpha quality auto install scripts, should now have some chance of working.
6. Improved standalone startup script, /usr/local/sbin is not always in the PATH.

V1.5.4 8/4/2007
1. Added ipfw support, thanks to Ronald Rood for preliminary testing on Mac OS X.
2. Changed options to be more firewall command neutral.
3. Added pattern "User ... not allowed ... not in AllowUsers", thanks to Ian Denton.

V1.5.5 17/5/2007
1. Changed docs to include BSD and Mac OS X install instructions.
2. Changed docs to mention the AUTH syslog service, which is used on some systems.
V1.5.6 31/5/2010
1. Added support for messages that span multiple lines.
2. All (except dropbear) sshd patterns are now together in the same configuration file.
3. Added support for Ubuntu, based on Debian templates.
V1.5.7 5/6/2010
1. Added Ubuntu and CentOS 5.5 startup files.
2. Improved install scripts.
3. Rewrote case by case examples, for a long time the default policy has been to allow illegal user names 3 chances, rather than 0 chances.
4. Renamed fifo from /var/log/sshd.fifo to /var/run/sshd.fifo


Written by Greg: R.Gregory at liv ac uk. Would welcome any comments.


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