denyhosts - protect your SSH server

Perhaps you, like many *nix users, like to remotely connect to your desktop and/or servers and thus are propably running an ssh-server. If so and you have ever checked logs for failed attempts to log in then you know that attempts to login with random usernames and passwords are made constantly. And finally, if you are like me, you are constantly worried that your username and the password, even though naturally a hard one to come up with, might one day be entered by person - or rather a brute force password cracking script - and thus your system getting compromized.

There is a simple tool to deny hosts from connecting the ssh-server (couple tools even, but here is one) after failing defined number of times - and if configured to, the program will send email report of new denied hosts and suspicious connection attempts. denyhosts is the program I use for this, and here is how to set up it:

First thing to do is to install the software. You can propably find it available on your linux distro / *nix variants software repository - if not, with necessary dependencies installed you can also install it from source tarball, but here’s howto install on Debian (Etch) (used on my desktop system…) and Fedora 7 (…and distro running this very server). On terminal window or console as a root enter:

Debian : apt-get install denyhosts

Fedora: yum install denyhosts

(And on Ubuntu the command used with debian would likely be entered as normal user with ’sudo ‘ in front of command)

Requirements for denyhosts to install & run are: Python v. 2.3 (or higher) and sshd server configured with tcp_wrappers support enabled.

Before setting up denyhosts: disable ssh logins as root

Before configuring denyhosts you might want to make sure that the ssh-server is configured to NOT accept logging in straight as root (…since it’s a username that is known to exist on ~99.9% of *nix systems and is the most dangerous - legitimate user can login with personal account and use su or sudo to root access). Check your ssh-server config file (usually at /etc/ssh/sshd_config) and make sure that value of PermitRootLogin is set to no. If it’s not, change the value, save file & restart the ssh server (usually /etc/init.d/ssh restart (or sshd instead of ssh on at least Fedora).

Setting up denyhosts to your needs

You might want to check out man page for denyhosts or further information on their site, however you might simply just go through following options (and explanations), use the default ones, my choices or your own preferences. Now open the file /etc/denyhosts.conf with your favorite text editor (no vi, emacs or even nano dissing here - although emacs naturally rocks ;) ). Go through at least following options:

Mandatory options

  • SECURE_LOG - the file containing sshd logging info May differ between systems - if installed from repository the correct one is propably already set. On Fedora / Red Hat this be SECURE_LOG = /var/log/secure and on Debian SECURE_LOG = /var/log/auth.log
  • HOSTS_DENY - file with restricted host access information. Usually /etc/hosts.deny.
  • PURGE_DENY - entries older than time set here will be removed from deny-list if denyhosts is ran with --purge commanline flag. For Debian this is by default set to nothing, which disables --purge action. On Fedora 7 install the default is 4 weeks (PURGE_DENY = 4w), which is the value I have set on both of my systems.
  • PURGE_TRESHOLD - Number of times a host can be purged from deny-list. I have left this unset, which defaults to unlimited times, however if you need the purge functionality you might want concider setting a value here to prevent continuously offending hosts from getting purged.
  • BLOCK_SERVICE - Service name to be blocked.
    To block ssh service for offending host: BLOCK_SERVICE = sshd
    To block ALL open services from offending host: BLOCK_SERVICE = ALL
    To only record offending hosts without denying access: BLOCK_SERVICE = (kinda defeats the idea of this article, but hey, it’s an option). I personally use blocking access to sshd service.
  • DENY_TRESHOLD_INVALID - Number of failed attempts with invalid username before denying the hosts. Default to DENY_TRESHOLD_INVALID = 5 which I use too.
  • DENY_TRESHOLD_VALID - Number of failed attempts with valid username (and incorrect password). The default is 10 but as a black hat that knows my username feels more threatening to me than a one that has to get both, username & password, guessed right I have set this to lower value: DENY_TRESHOLD_VALID = 4.
  • DENY_TRESHOLD_ROOT - Although (and because of) root-login is already disabled on ssh server (at least on mine) a login attempt as root can clearly be defined as non-legitimate attempt I want any host trying it to get denyed right after first attempt. Default value of 1 is thus fine here - unless you actually want to keep root-logins allowed (which I highly recommend against) in which case you might want to change this to not get denyed yourself because of password typo.
  • DENY_TRESHOLD_RESTRICTED - not delt with on this article, refer denyhosts.conf comments, man page or website.
  • WORK_DIR - Path used by denyhost to write it’s data. Created if not existing, set by default to /var/lib/denyhosts.
  • SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS - If set to YES (default & mine), report all suspicious login attempts from allowed host. No disables reporting of these.
  • HOSTNAME_LOOKUP - YES or NO. If set to YES, lookup hostname for each reported IP and report hostname (if available) as well.
  • LOCK_FILE - not delt with on this article, default value should need no changes.

Optional settings

  • ADMIN_EMAIL - set to email address where you want to receive reports of denyed hosts and suspicious login attempts. Leave blank if you want no email reports. eg. ADMIN_EMAIL = robsku@fiveam.org
  • SMTP_HOST & SMTP_PORT - email server address and tcp port to use when sending email reports. SMTP_PORT is usually set to 25 and for example in my case, using Welho ISP I have it set as SMTP_HOST = smtp.welho.com.
  • SMTP_USERNAME & SMTP_PASSWORD - if the email server needs credentials, set the username & password here.
  • SMTP_FROM - Specify “From:” address for emails. Default: SMTP_FROM = DenyHosts <nobody@localhost>
  • SMTP_SUBJECT - “Subject:” field used in emails. Defaults to DenyHosts Report and with this server I have set it as SMTP_SUBJECT = DenyHosts Report from Salamanteri (and “Raippa” instead of “Salamanteri” on my desktop).
  • SMTP_DATE_FORMAT - Explained in denyhosts.conf, I have left it at default value (on Debian the setting was commented out by default).
  • SYSLOG_REPORT - Defaults to NO. If set to YES, when denied hosts are reported the data will be sent to syslog. I use the default.
  • ALLOWED_HOSTS_HOSTNAME_LOOKUP - not dealt on this article, refer to documentation.
  • AGE_RESET_VALID - Specifies period of time between failed login attempts that, when exceeded will reset failed count for host to 0. This can prevent legitimate users getting banned because of failed attempts that sometimes can happen to the best of us. Of course if DENY_TRESHOLD_VALID is set to 1 then this setting is useless. I have it set to default as DENY_TRESHOLD_VALID = 5d (5 days), so failings because of typo on password are forgotten after 5 days.
  • AGE_RESET_ROOT - Same as above, but for login attempts as root. Default is 25d but I have commented out this setting, so for failed roo-login attempts the count is never reseted (as I am only one having rights to root account and know that any attempts to login as root are non-legitimate.
  • AGE_RESET_RESTRICTED - Similiar to two above settings, but for restricted usernames. Refer to documentation.
  • AGE_RESET_INVALID - Same as three settings above but for failed login attempts with invalid username. I use the default of 10d (10 days).
  • RESET_ON_SUCCESS - Default: “no”. I have set it to “yes” which causes failed attempt count for host to be reset to 0 after successful login.
  • PLUGIN_DENY - Unset by default. Can be set to any command that will be excecuted when host is added to HOSTS_DENY file with the hostname/ip as only argument. Left it unset.
  • PLUGIN_PURGE - Similiar to PLUGIN_DENY, except excecuted when a host is purged from DENY_HOSTS file. Left unset.
  • USERDEF_FAILED_ENTRY_REGEXP - not dealt with here, refer to documentation.

“cron-job” mode & daemon mode (with yet more settings).

There are two ways that denyhosts can be ran. On Debian & Fedora denyhosts installs with denyhosts set to run in daemon mode, which will keep it running constantly in the background. For daemon mode some further settings still exists (see below next chapter). The daemon mode should be preferrable in most cases.

The other way is to set denyhosts to run as cron-job between time intervals of your choice. Everytime it’s ran the program will parse ssh server access log for new entries and react accordingly to any failed attempts. With the settings I have explained above the program is ready to run in cron job. To set denyhost up as cron job you can do one on following - or something similiar:
In /etc/crontab adding following line will run denyhosts every 10 minutes:

0,10,20,30,40,50 * * * * root /usr/bin/denyhosts.py -c /etc/denyhosts.conf

To run purging old entries every morning (at 5am) you could add this:

0 5 * * * root /usr/bin/denyhosts.py -c /etc/denyhosts.conf --purge

Note that on some systems (eg. on Fedora) the default is to run as daemon but also a cron-job file is installed at /etc/cron.d/denyhosts with commented out definitions, so edit that instead of /etc/crontab.

Daemon mode settings
In case you already saved changes to /etc/denyhosts.conf and exited editor, open it up again if you are to run denyhosts as daemon. Following settings are daemon mode specific:

  • DAEMON_LOG - Default: /var/log/denyhosts. The logfile that denyhosts reports its status. Leave blank to disable logging.
  • DAEMON_LOG_TIME_FORMAT - timestamp format for log. Explained in the file.
  • DAEMON_LOG_MESSAGE_FORMAT - message format for log. Explained in the file.
  • DAEMON_SLEEP - time spent sleeping between polling ssh access logfile. By default will poll the log every 30 seconds (DAEMON_SLEEP = 30s).
  • DAEMON_PURGE - sets how often will old entries in DENY_HOSTS file be purged. Defaults to DAEMON_PURGE = 1h (every 1 hour), I set it to 1d (day). If PURGE_DENY is blank then this has no effect.

Now the essentials have been set up. There are still settings for “daemon synchronization” available - that would allow the daemon to send & receive denied hosts data between other denyhosts daemons worldwide. This is disabled by default and does not interest me personally so if you want to read about that I suggest you browse to http:/denyhosts.sourceforge.net/faq.html#sync.

Running as daemon
To manually start, stop, restart, etc. you can, as root, run:

/etc/init.d/denyhosts {start|stop|status|restart|reload|force-reload|condrestart}

After editing configuration file, you should atleast run /etc/init.d/denyhosts restart if the daemon is already running - and using “start” instead of “restart” will start running daemon if not started yet.

Different systems have different ways of setting if a daemon is to be started automatically on boot. On Fedora it’s done with chkconfig command, like this:

# To list whic runmodes to run denyhosts in
chkconfig --list denyhosts
# Set denyhosts to run automatically
chkconfig denyhosts on
# Disable denyhosts from beeing ran as daemon
chkconfig denyhosts off

You may still need to run /etc/init.d/denyhosts {start|stop} to start or stop the daemon now, chkconfig settings will be applyed only on initlevel change (eg. when booting up or shutting down).
On Debian there is more complicated command, update-rc.d which I have little interest to since denyhosts was automatically configured to run and started up after install.

You should now have a functioning denyhosts setup which will make breaking into your ssh server via brute-force/guess login attempts by black hats much harder than without this excellent tool.

More about denyhosts

You can read more about denyhosts from the official homepage - they also have quite fullfilling FAQ explaining the program more detailed way. As always, leave a comment if you found this article usefull (or if you noticed any errors in it).

admin

Author is a 29 years old linux zealot and hacker from Finland.

You can leave a response, or trackback from your own site.

2 Responses to “denyhosts - protect your SSH server”

  1. Privacy Seeker Says:

    I have to say, SSH was the best thing they ever came out with. You can’t beat its security nor its reliabilty.

  2. Robsku Says:

    True - amazingly some organizations still use FTP and Telnet. Telnet has no use unless it provides some other system than regular *nix shell (like MUD for example) and FTP is obsolete for anything else than anonymoys access.

    SCP/SSH are the thing that has replaced then - and even regular desktop *nix with SSH server gets so much unauthorized login attempts that systems like denyhosts are a very good security method even with SSH (since eventually someone from particular IP might get credentials of some user right and login).

    Shield your system at least with good firewall, SSH if you want remote connection (or “FTP with encryption” that is SCP, part of SSH) and denyhosts or something like that.

    If you have no denyhosts and SSH open at TCP/22 just check from SSH logs how many attempts to login there are every day - huge amount even if you just run regular desktop system with SSHD for remote connection.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>