Protect your ssh-servers, ban offending hosts
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 usesu 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/secureand on DebianSECURE_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
--purgecommanline flag. For Debian this is by default set to nothing, which disables--purgeaction. 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 = sshdTo block ALL open services from offending host:BLOCK_SERVICE = ALLTo 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 = 5which 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.confcomments, 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.
- 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 Reportand with this server I have set it asSMTP_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.
/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.confTo run purging old entries every morning (at 5am) you could add this:
0 5 * * * root /usr/bin/denyhosts.py -c /etc/denyhosts.conf --purgeNote 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.
/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 offYou 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).NOTE About this post!
This blog entry contains exactly same text as the static page “Linux/Unix Guides » denyhosts - protect your SSH server“, however the comment sections are different. You can comment here as well but if it’s important, please go to the page and send your comment there. This way your comment wont be lost in time but is seen on page listed under Linux/Unix Guides.Related posts
Tags: crackers, guide, howto, Linux/Unix, Linux/Unix Software, security, tools

January 22nd, 2009 at 10:36 am
I think your blog need a new wordpress template. Downalod it from http://genericwpthemes.com . The site has nice and unique wordpress templates.
January 24th, 2009 at 1:17 am
@WP Themes
Thanks but no thanks - I like my carefully selected and customized for myself version of Simplicity theme. Still even though your comment is off-topic I approved it because you provide a link with some good WP themes - maybe some visitor will find it usefull.
February 16th, 2009 at 12:41 am
Your site does not correctly work in safari browser
February 16th, 2009 at 8:17 am
@Thibiachoor
That’s unexpected. I was unable to get Safari for Windows to run under Linux+Wine so I cant test it :/ Would you be so kind to tell me where and how exactly does my site show incorrectly under Safari so that I could try and fix it? :)
edit: I checked later with Konqueror that I hear uses the same rendering engine (KHTML) and also checked the site with one of the broweser screenshots services on web and both Konqueror and latest Safari seemed to show it correctly. Please tell me what version of Safari are you using and what are the errors.
February 28th, 2009 at 1:11 pm
I must say that you provide genuine, quality information. Thanks for this!
BTW, dpn’t you think your blog needs a better wordpress template?
February 28th, 2009 at 9:00 pm
@Applebees
Thank you. As for the template, I actually specifically looked for something very simple but stylish, found The Simplicity theme which I personally like although I needed to modify it just a tiny bit to my needs. Most importantly I think it provides a clear and easy to read/use interface :)
June 8th, 2009 at 1:06 pm
а ты нравится публикуете ролики вблоге?
June 15th, 2009 at 9:50 pm
Hi! Enjoyed your article, thanks! best regards, P
July 2nd, 2009 at 7:50 pm
Your blog is so interesting! I have subscribed on rss and I will read it regullary/
July 3rd, 2009 at 12:00 pm
Very interesting blog! Subscribed on rss. Regular will read it