sshutout - A Daemon to Stop SSH Dictionary Attacks

Author: Bill DuPree
Name: sshutout.c
Version: 1.0.6 (2009-12-05)
Language: C
Inception: April 29, 2006
License: GPL

Introduction:

This is a Linux daemon, written in C, that periodically monitors log files looking for multiple failed login attempts via the Secure Shell daemon (sshd, or optionally, sshd2). The daemon is meant to mitigate what are commonly known as "dictionary attacks," i.e. scripted brute force attacks that use lists of user ID's and passwords to effect unauthorized intrusions. Typically such attacks fill the system logs with hundreds or even thousands of log entries for the failed login attempts. Aside from the nuisance of wasted space, wasted bandwidth, and reduced signal to noise ratio in the logs, the attacks can pose a real danger to systems with weak ID and password combinations.

The sshutout daemon blunts such attacks by creating firewall rules to block individual offenders from accessing the system. These rules are created when an attack signature is detected, and after a configurable expiry interval has elapsed, the rules are deleted.

While sshutout can help reduce the severity and impact of dictionary attacks, it is by no means a substitute for a good password policy. A password policy is the front line of defense against intrusion and should be given careful consideration. The sshutout daemon is merely one small tool intended to help reduce log clutter and diminish the incentive to mount dictionary attacks.

Description of Algorithm:

The sshutout algorithm follows a pretty standard model for *nix daemons. The program starts, assumes a fairly safe set of built-in default values, then consults an optional configuration file to further refine these values, and finally consults the command line for arguments specifying overrides. The program checks to see that it has the required superuser authority and then forks. Its newly forked daemon process detaches from the console; the original process terminates.

Next, an initial whitelist is constructed from the addresses of all active network interfaces. In addition, the name servers and default route are added to this whitelist. Finally, host addresses specified in the configuration file or command line are appended to the list.

Appropriate signal handling is now set up. In this case, SIGHUP, the hang-up signal, is provided with a handler to refresh the daemon's operating parameters from the configuration file. The other handled signals, i.e. SIGTERM and SIGPWR (and possibly SIGINT and SIGQUIT if not running as a daemon), are set up to cause a graceful termination of the daemon process.

After signal handling has been initialized, the daemon enters its main processing loop. The loop spends most of its time in a sleep state, but when it does execute, which is approximately once per second, it examines all entries in its blocked hosts list to see if any are ready to expire. Those that are expiring are removed from the list and are also unblocked at the firewall through removal of the corresponding rule.

The daemon's next action is to determine whether its polling interval has elapsed. If it has not yet elapsed, then the daemon goes back to sleep. If the interval has elapsed, then the daemon examines the host's configuration to see if any changes are required to the whitelist, for example, if any new interfaces have come up, or if the addresses associated with any interfaces have changed, etc. Next, the daemon will examine the specified log file to look for failed login attempts. It tallies a count of all failed login attempts for each unique host address over the span of the given polling interval. Those tallies that exceed the specified threshold are moved to the list of blocked hosts (unless, of course, they are in the whitelist.) Each item added to the blocked list is also blocked at the firewall through the addition of a suitable rule. This processing continues indefinitely until the daemon is signaled to stop.

Installation:

The sshutout daemon is fairly simple to install provided you have a GCC toolchain that is suitable for building binaries for your target system. To build the binary, run the following commands:

$ su -
# tar -xzvf sshutout-1.0.6.tar.gz
# cd sshutout-1.0.6
# make
# make install

The installation process will place three new files onto your system. These are:

/usr/local/sbin/sshutout
/usr/man/man8/sshutout.8
/etc/sshutout.conf

The first file is the executable binary for the daemon. The second file is a man page, and the third file is a sample configuration file. These three files may be copied to other systems as needed to effect additional installations assuming the processor architecture and object libraries are compatible.

To complete the installation, you will need to edit your system startup scripts and add a line or two to invoke the sshutout daemon. For example, insert the following lines just after the invocation of sshd:

if [ -x /usr/local/sbin/sshutout ]; then
   rm -f /var/run/sshutout.pid
   /usr/local/sbin/sshutout
fi

You should also customize the configuration file: "/etc/sshutout.conf" to reflect your target system's particular needs. It is especially important to make sure that the sshd_log_file parameter is set to the proper path (see the table in the Download section for hints.) After customization, you may either invoke sshutout directly (as root), or you may reboot your system.

Program Invocation:

This program is a system daemon that is intended to be run from the server startup scripts. It has the following usage:

# sshutout -?
sshutout ver. 1.0.6 -- (C)Copyright 2009 - Bill DuPree
All rights reserved.

Usage:
        sshutout [-d delay] [-f config_file] [-i poll_interval]
                 [-l input_log_file] [-p pid_file] [-s output_log_file]
                 [-t threshold] [-w host_list] [-?] [-2] [-D] [-e] [-u]
Where:
  -?  Gives this help message
  -2  Specifies that defaults for the sshd2 daemon are assumed
  -D  Means do not run as a daemon.
  -d  Takes a numeric value giving the number of seconds to firewall attackers
  -e  Turns off auto whitelisting of default route and name servers
  -f  Takes an alternate file name for the input configuration file
  -i  Takes a numeric value giving the polling interval in seconds
  -l  Takes an alternate file name for the input log file
  -P  Firewall IP addresses doing port scans
  -p  Takes an alternate file name for the output PID file
  -s  Takes an alternate file name for the output log file
  -t  Takes a numeric threshold value for firewalling failed login attempts
  -u  Turn on sensitivity to "Illegal/Invalid user" attempts
  -w  Takes a comma separated list of whitelisted host addresses

A sample configuration file is shown below. The sample shows all configurable parameters and their default settings. As is typical, a pound sign, i.e. a '#' character, introduces comment information. In other words, anything on a line following the pound sign is ignored. (As such, please note that all parameter lines are commented out in this sample file.) Blank lines and white space may be used as desired for clarity and aesthetics. All parameter lines follow the form:

<parameter_name> = <parameter_value>

The configuration file, if it exists, is normally found at the path:

/etc/sshutout.conf

but you may override the default location by using the -f option on the command line during program invocation.

# Sample configuration file for the sshutout daemon.
# The (commented out) values shown below are
# the defaults if not specifically overridden
# in the configuration file or on the 
# command line.

# The polling interval is given in seconds and determine how often
# the ssh log is examined. Range 30 - 300

#polling_interval = 60

# The delay penalty is given in seconds and specifies how long the
# firewall rule should remain effective. Range 60 - 86400

#delay_penalty = 300

# The threshold value gives how many failed login attempts will trigger a
# block at the firewall. Value >= 3

#threshold = 4

# The following parameter gives the name of the file that is scanned for
# ssh login attempts. Typical values are:
#
#     /var/log/messages  (default)
#     /var/log/secure
#     /var/log/auth.log
#
# Consult your Linux distribution for the correct setting.

#sshd_log_file = /var/log/messages

# The next parameter gives the name of the file where attacker
# IP addresses are logged.

#sshutout_log_file = /var/log/sshutout.log

# This parameter gives the name of the ssh daemon that we are
# monitoring. Openssh names its daemon, "sshd", while
# ssh.com's daemon is named, "sshd2" 
# Legal values are restricted to sshd or sshd2

#ssh_daemon = sshd

# The sshutout daemon process' PID is stored in this file.

#pid_file = /var/run/sshutout.pid

# The whitelist value is specified as a comma separated list of IPv4
# addresses (dotted quad or host name) which will be ignored by
# the daemon, i.e. they are never firewalled by the daemon.
# During normal operation, the default route, name servers, and
# addresses of all active interfaces are automatically part
# of this whitelist, so they don't need to be specified here. 
# Example: whitelist = 12.13.14.15, 120.20.101.30, techfinesse.com 

#whitelist = 

# Enabled by default, this parameter automatically whitelists 
# the default gateway and name servers.
# Valid values (case insensitive):
#	y, n, yes, no, 1, 0, t, f, true, false, on, off

#auto_whitelist = yes

# Should we firewall portscans seen by ssh daemon, 
# i.e. those hosts whose probes leave those 
# "Did not receive identification string from..." messages? (default no)
# Valid values (case insensitive):
#	y, n, yes, no, 1, 0, t, f, true, false, on, off

#squelch_portscan = no

# Should we monitor and count "Illegal user" or "Invalid user" attempts
# as well as failed logins? Valid values (case insensitive):
#	y, n, yes, no, 1, 0, t, f, true, false, on, off

#illegal_user = no

A sample invocation is shown below to illustrate command line usage. In this example the -i option is employed to explicitly set the polling interval to 30 seconds, the -d option is used to override the default penalty with a value of 900 seconds, the -t option is used to set the threshold to 3 attempts, and the -P option is invoked to enable squelching of hosts that scan the ssh port.

# sshutout -i 30 -d 900 -t 3 -P
sshutout ver. 1.0.6 -- (C)Copyright 2009 - Bill DuPree
All rights reserved.

*** The sshutout 1.0.6 daemon has started ***
sshutout configuration follows:
Configuration file: /etc/sshutout.conf
SSH Daemon: sshd
Input log file: /var/log/messages
Output log file: /var/log/sshutout.log
PID file: /var/run/sshutout.pid
Polling interval: 30 seconds
Threshold: 3 attempts
Delay penalty: 900 seconds
Portscan squelching is enabled
Illegal/Invalid user squelching is disabled
Whitelist:
  12.127.16.83
  12.127.17.83
  192.168.1.1
  127.0.0.1
  192.168.1.222

To have the daemon reload the configuration file, which is especially useful for changing operational parameters "on the fly," it is a simple matter to execute, as root, the command:

kill -s SIGHUP `cat /var/run/sshutout.pid`

Change Log:

RevisionDateInitialDescription
1.0.02006-05-30WDInitial release
1.0.12006-06-12WDFixed crash caused by "Did not receive identification string from UNKNOWN" messages
1.0.22006-06-18WDFix to get actual default route as opposed to first gateway encountered in routing table. (Many thanks to Hansjürg Wenger!) Added option to disable/enable automatic whitelisting of default gw and name servers.
1.0.32006-06-28WDAdded -u option to turn on sensitivity to "Illegal user" attempts.
1.0.42007-11-08WDMade -u option sensitive to "Invalid user" attempts as well. (Thanks to Peter McClure!)
1.0.52007-12-30WDFixed -u option (ashamedly wearing paper bag on head) Thanks to Ralph Slooten!
1.0.62009-12-05WDAdded detection for "UNKNOWN USER", larger config file line buffer, and corrected open() calls. (Thanks to Michael Shigorin & A.Kitouwaykin at ALT Linux)

Download:

The following archive contains the complete C source code for the sshutout daemon, a Makefile, and some ancillary documentation.

Ver. 1.0.6 Compressed Tar (gzip): Download

The code is specific to GNU/Linux based operating systems and was developed and tested using GCC 3.3.6 on Slackware Linux 10.2 running in an x86 environment. Simple remakes are known to run on:

Linux DistributionLog File UsedProcessor Architecture
CentOS 5.4 (Red Hat variant)/var/log/securex86
BLAG 30003 (Red Hat Fedora variant)/var/log/securex86
Debian 3.1 "sarge" /var/log/auth.logAlpha AXP
kubuntu 5.10 (Debian variant)/var/log/auth.logx86
SuSE 9.1/var/log/messagesx86
OpenSUSE 10.1/var/log/messagesx86
Slackware 10.x/var/log/messagesx86
Yellow Dog Linux 4 (Red Hat variant)/var/log/securePowerPC
Slamd64 10.2b (Slackware variant)/var/log/messagesx86_64

License:

This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

Contact:

Email: Bill DuPree (bdupree_AT_techfinesse_DOT_com)
Post: Bill DuPree, 609 Wenonah Ave, Oak Park, IL 60304 USA

Copyright © 2009, Bill DuPree. All rights reserved.