This how-to will explain how to setup DenyHosts on a RedHat-based (RHEL, CentOS, or Fedora) Linux server to automatically add remote IP addresses that repeatedly fail login attempts to your server’s /etc/hosts.deny file in an attempt to block SSH brute force/dictionary attacks.
A Little Background about SSH Attacks
If you’ve got a RHEL / Centos / Fedora server, then the most likely way you access your system is via Secure Shell, more commonly referred to as SSH.
The problem is that all Linux hackers also happen to know that you’re using SSH, and they use thousands of remote systems (many of which are personal computers that have been hijacked without the owner’s consent via some sort of virus, which we call a zombie host) scanning the Internet looking for servers that respond to SSH requests. When a hacker finds one, they’ll generally begin what’s called a brute force or dictionary attack. This most basic attack uses a list of common usernames (such as root, apache, admin, bob, john, sue) and tries to log in to your server with those usernames, using a long list of dictionary words as possible passwords (with automated variations on capitalization). Because this process is automated, because the bandwidth and resources of a zombie host are essentially “free” to the hacker, and because most Linux servers have no restrictions on the number of wrong username/password combinations they allow when attempting to log in, these types of attacks are extremely common. Hackers can run this type of attack against your server all day every day – and you might not ever know about it… until it’s too late and they’ve taken control of your system. I see hundreds of attempts every day on my servers, but I use a few tools and tricks to help keep them out.
First Line of Defense: Use a Strong Password
The easiest defense against a brute force attack is a strong password. There are many suggestions and guidelines as to what constitutes a strong password, but the old adage of “easy for you to remember, hard for others to guess” is a good starting point. And those “others” should include zombies running automated dictionary attacks – meaning you should never use any common word (such as a name) or a word that might appear in a dictionary as your password (and never EVER use your username as your password). The best password is one that is some combination of upper and lower case letters, numbers, and any special characters that might be allowed on your system. I usually recommend creating a phrase that is memorable or meaningful to you, which includes numbers and punctuation. As an example, let’s use the first line from the U.S. Air Force song “Off We Go, Into the Wild Blue Yonder!” Take the first letter of each word (changing any letter “O” into the number “0” and the letter “I” in to the number “1”) then include the punctuation at the end and you get a password that would be impossible to guess: 0wg1tWBY! You can capitalize whichever letter(s) you like, and in your own passwords you can swap the number “5” for the letter “S” or the number “3” for the letter “E” or the dollar sign “$” for the letter “S,” and so on.
Using DenyHosts to Stop Dictionary Attacks Quickly
However, even with a secure password, it’s a good idea to slow down hackers’ attempts at dictionary attacks with a powerful (and FREE!) tool called DenyHosts. It’s a great little script that watches all attempted logins to your system (both successful and unsuccessful), records details about the attempt (but never the password), and then follows your instructions as to how you’d like to deal with unsuccessful attempts. The default settings will block the IP address of a remote server so that it can no longer connect to your machine via SSH after a certain number of failed login attempts (5 failures for user accounts that don’t exist, 10 failures for user accounts that do exist, and a single failed attempt for the root account). All of these settings are easily configurable, but I’ve found the default settings to be strong enough to thwart hackers, yet loose enough to allow for human error when users need a few guesses at their passwords.
Step 1: Install DenyHosts using YUM
The easiest way to get up and running with DenyHosts on a RedHat / CentOS/ Fedora server is with yum. Simply type:
yum install denyhosts
By default, Fedora servers should have the proper repositories to install DenyHosts with yum, but default RHEL or CentOS servers will likely need to install the EPEL repository before this will work. I’ve found some path location discrepancies between the versions at RPMForge and EPEL, so this howto will assume you’re using the default Fedora yum install or version denyhosts-2.6-5.el5.noarch from EPEL (which use the same paths).
Step 2: Enter your Allowed Hosts
It would be a shame to be locked out of remote access to your Linux box by your own security measures, so the next step is to add any hostnames or IP address that you know are “safe” to a text file. DenyHosts will check that file and will never block access from that location, no matter how many failed login attempts come from that host. Use this file sparingly, and only for hosts that are under your control. Using your favorite text editor, open /var/lib/denyhosts/allowed-hosts. The default looks like this:
# We mustn't block localhost 127.0.0.1
Of course, you’ll want to leave 127.0.0.1 in the file, otherwise you’d block your own server from being able to connect to itself. Add any other IP addresses or hostnames (DenyHosts will resolve hostnames’ IP addresses) that you wish to explicitly allow here. You can use wildcards (*) in the file. For example, if you never want to block IPs from your internal network, you could make your allowed-hosts file look like this:
# We mustn't block localhost 127.0.0.1 192.168.1.*
Step 2: Edit the Default DenyHosts Configuration (optional)
This is a completely optional step, because I find the DenyHosts’s default configuration options to be fine for most applications. However, if you’d like to change any of the default options, or just take a peek at what they are, simply edit /etc/denyhosts.conf with your favorite text editor. The comments in the configuration file are excellent, and do a good job of explaining what each of the options control.
Step 3: Set DenyHosts to Start on Boot
Security measures are only useful if they are active, so I recommend setting DenyHosts to start automatically if you reboot your system. Do:
chkconfig denyhosts on
and you’ll be good to go.
Step 4: Start DenyHosts
Simply type:
service denyhosts start
and you’re off and running!
Step 5: Testing
Of course, you’ll probably want to test to make sure DenyHosts is blocking hackers as expected. IMPORTANT! Make sure you keep at least one shell logged in to your server while you test! That way, if do you accidentally lock out your IP address, you’ll still be logged in and able to remove the blocked IP from the blocklist (you could also log in physically on the machine if you have physical access to the box).
It is possible to test DenyHosts with only two machines (your local desktop and your remote Linux box) by keeping one session logged in and starting a separate connection to test failed logins, but that’s dangerous because if you lock out your own IP address and then lose the connection to your logged in session, you’ll need to access the server from a third server whose IP isn’t blocked, or login at the physical terminal. It’s safer to use a third system.
From your desktop, ssh to your Linux box and log in as normal. Do:
tail -f /var/log/denyhosts
to see the DenyHosts log file in real-time. Next, ssh from your desktop to a third server (whose IP will be blocked during testing). Try to login with a bogus username and password (if you try to login as root, the default failure thresholds will be lower). After enough failed attempts, the /var/log/denyhosts logfile will tell you that a new host has been added to the denied hosts list, and your server will send an alert email to the root account (unless you turned that off in /etc/denyhosts.conf).
DenyHosts has added the offending IP address to your system’s /etc/hosts.deny file, which blocks that IP from connecting via SSH. Good job!
Step 6: Removing Denied Hosts
If you want to remove the test IP you just blocked from /etc/hosts.deny, or if you ever accidentally locked out one of your own hosts, you might assume that you can simply remove the offending IP from /etc/hosts.deny and you’re good to go… but you would be wrong. 🙂
DenyHosts keeps track of all login attempts in a number of files in its work directory, so you’ll need to remove the offending IP address from each of those files. If you installed via YUM as shown in this how-to, the work directory containing these files is /var/lib/denyhosts. To erase the address:
- Stop DenyHosts with service denyhosts stop
- Remove the IP address from /etc/hosts.deny
- Edit the following DenyHosts work files and remove any lines containing the IP address:
- /var/lib/denyhosts/hosts
- /var/lib/denyhosts/hosts-restricted
- /var/lib/denyhosts/hosts-root
- /var/lib/denyhosts/hosts-valid
- /var/lib/denyhosts/users-hosts
- Optionally consider adding the IP address to /var/lib/denyhosts/allowed-hosts (as appropriate)
- Start DenyHosts with service denyhosts start
Keep in mind that not all of the files in the /var/lib/denyhosts directory will contain the offending IP address, so you may want to use grep to determine which files contain the IP address. For example, to see which files in that directory contain the IP address 12.456.78.90, do:
cd /var/lib/denyhosts grep 12.456.78.90 *
After doing this manually for a few years, I stumbled across a pretty robust script for automatically doing all the above steps, written by someone named Cybernitus. Save the script as denyhosts-unban.sh, set permissions with chmod 755 denyhosts-unban.sh, then run it with the –help flag for options.
Additional Reading and Tweaking
First, I recommend visiting the DenyHosts website and reading the excellent documentation in their FAQ for more information on how you can tweak and extend DenyHosts’ functionality. I recommend checking the section of their FAQ that talks about synchronization to see if it might be right for you (it is for me – I use it on all my servers).
For additional reading on securing SSH on a RedHat-based server, I recommend reading this article on Securing SSH from FedoraUnity. In addition to DenyHosts, it has a number of excellent suggestions for further locking down your SSH.
Please feel free to leave comments and suggestions!