=head1 NAME

sshdfilter - sshd brute force blocker

=head1 SYNOPSIS

B<sshd> wrapper script that generates B<iptables> DROP rules when B<sshd> reports any of i) no identify string sent by client ii) attempted login to a non-existant account iii) mupliple password failures for a valid account. DROP rules are added in realtime. There are two install routes, either as an B<sshd> wrapper, in which case B<sshd> messages are read directly by B<sshdfilter>, or as a separate standalone program that parses B<sshd> output via a didicated syslog named pipe.

=head1 DESCRIPTION

B<sshdfilter> blocks the frequent brute force attacks on B<ssh> daemons, it does this by directly reading the B<sshd> logging output (or syslog output) and generating B<iptables> 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 block rules largely by user name or by the type of user name.

There are two install routes, the old style B<sshdfilter> starts B<sshd> itself, having started B<sshd> with the I<-e> and I<-D> options. The newer style uses a syslog configuration line that writes B<sshd> messages to a dedicated named pipe, normally F</var/run/sshd.fifo>. Regardless, this means B<sshdfilter> can see events as they happen and act on them as they happen. B<sshdfilter> then looks for lines of the form:

C<Did not receive identification string from x.x.x.x>
C<Illegal user x from x.x.x.x>
C<Failed password for illegal user x from x.x.x.x port x ssh2>
C<Failed password for x from x.x.x.x port x ssh2>

When B<sshd> produces any of these messages, the response of B<sshdfilter> is defined by the configuration file F</etc/sshdfilterrc>. The default configuration file defines the first message as in instant block event that will install an iptables rule dropping that IP. The next two lines are given one chance (ie. this chance) before an iptables dropping rule is generated. The latter message is given 3 chances before it is blocked.

These are in fact example messages, the exact wording varies between Linux distributions, so the distribution B<sshdfilterrc> exists as a large header containing default policies, and a footer F<patterns/>, each file containing patterns for each Linux/sshd distribution. On installation, the header and the (hopefully) correct footer are added together to create your F</etc/sshdfilterrc>.

All new rules are inserted into a custom B<iptables> chain, and to prevent the chain from becoming overloaded with old rules, old rules are deleted. Rule duration is also specified in the configuration file.

Taking some statistics from my logs before B<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 B<sshdfilter> installed, taking each attack on a case by case basis:
 B<1)> 347 attempts becomes 0 attempts - first attemped guess was for a non-existant user, so was instantly blocked.
 B<2)> 306 attempts becomes 0 attempts - same reason, non-existant user.
 B<3)> 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.
 B<4)> 115 attempts becomes 1 attempt - same as previous.
 B<5)> 127 attempts becomes 3 attempts - many initial guesses for root account, so B<sshdfilter> blocks after the first 3 failed attempts.
 B<6)> 18 attempts becomes 0 attempts - first attempted guess was for a non-existant user, so was blocked instantly.
 B<7)> 554 attempts becomes 3 attempts - many initial guesses for root accont, so B<sshdfilter> blocks after the first 3 failed attempts.
 B<8)> 107 attempts becomes 1 attempt - first guess was for a valid user (nobody), second guess was for a non-existant user so was blocked.
 B<9)> 9 attempts becomes 0 attempts - first guess was for a non-existant user so was blocked instantly.
 B<10)> 52 attempts becomes 3 attempts - many initial guesses for root accont, so B<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, B<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, B<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.

=head1 COMPATIBILITY

Right now B<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, Slackware and gentoo, and the many derivatives. It also now supports ipfw for BSD, Solaris and MacOSX support. It also works with Dropbear, the light weight sshd server. Each distribution uses different logging messages, so B<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.

=head1 INSTALLATION

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

=head1 OPTIONS

If your B<sshdfilter> is installed as a wrapper to B<sshd>, all options on the command line are passed to B<sshd>, B<sshdfilter> takes all its options via the configuration file F</etc/sshdfilterrc>. See its man page for more information on the options.

If your B<sshdfilter> is installed standalone and reads B<sshd> messages via a syslog fifo, B<sshdfilter> takes the option B<< logpid=<pid of sshd> >>. This will only be usful if you run multiple sshdfilters, as this allows sshdfilter identify messages from a particular sshd. sshd messages in syslog are from the children of the main sshd daemon, so sshdfilter will accept only messages from children of this pid.

=head1 FILES

F</usr/sbin/sshdfilter> - main sshdfilter code.
F</etc/sshdfilterrc> - sshdfilter configuration file.

F</etc/init.d/sshd> - modified sshd startup script, so sshdfilter is run instead of sshd.
or
F</etc/init.d/sshdfilter> - standalone startup file.
F</etc/sshdfilter.ipfw> - ipfw state file, see INSTALL.ipfw

=head1 DOWNLOAD

The latest B<sshdfilter> is available from S<L<http://www.csc.liv.ac.uk/~greg/sshdfilter/>>

=head1 BUGS

None known. More likely there are features you don't like.

=head1 SEE ALSO

sshdfilterrc(5)


=head1 AUTHOR

Written by Greg: greg at csc liv ac uk. Would welcome any comments.

LogWatch script written by Tommo: sshdfilter at gmail com.

=head1 LICENSE

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

