Securing SSH

After configuring my server, I decided to set up SSH on it so I could remotely send commands to the server. All was working fine and I managed to connect Prompt to my server and SSH into my server from my iPad and iPod touch. However, after I decided to look at /var/log/secure.log in Console, I noticed messages like this:

Sep 13 07:04:35 server sshd[23502]: Invalid user oracle from 94.249.186.66
Sep 13 07:04:35 server sshd[23503]: input_userauth_request: invalid user oracle
Sep 13 07:04:35 server sshd[23503]: Received disconnect from 94.249.186.66: 11: Bye Bye
Sep 13 07:04:36 server sshd[23507]: Invalid user test from 94.249.186.66
Sep 13 07:04:36 server sshd[23508]: input_userauth_request: invalid user test
Sep 13 07:04:36 server sshd[23508]: Received disconnect from 94.249.186.66: 11: Bye Bye

Several IPs were trying to hack into my server.

Installing DenyHosts

After some research, I decided to install DenyHosts on my server. This monitors the SSH log file (secure.log if you’re on a Mac) and adds IPs that make too many incorrect attempts to access your server to your /etc/hosts.deny file. You can see how successful this program is by looking at the statistics some users are contributing. You can tell DenyHosts to use these statistics by enabling synchronisation mode. To install DenyHosts, download it, unarchive it, and cd into the directory (cd ~/Downloads/DenyHosts-2.6). Then run the setup script with sudo python setup.py install. Once DenyHosts has installed, edit the configuration file:

cd /usr/share/denyhosts
cp denyhosts.cfg-dist denyhosts.cfg
vi denyhosts.cfg

You can view my example configuration file on GitHub. Next, set up the DenyHosts daemon:

cd /usr/share/denyhosts
cp daemon-control.dist daemon-control
vi daemon-control

You should only need to edit lines 14–16. Here are the lines from my daemon-control:

DENYHOSTS_BIN   = "/usr/local/bin/denyhosts.py"
DENYHOSTS_LOCK  = "/var/lock/subsys/denyhosts"
DENYHOSTS_CFG   = "/usr/share/denyhosts/denyhosts.cfg"

To check everything works, try launching the daemon:

sudo /usr/share/denyhosts/daemon-control start

You could use this command to start the daemon every time you boot up your server. Alternatively, you could load it into launchctl (or cron). To load it into launchctl, first create the file /Library/LaunchDaemons/com.denyhosts.dh-daemon.plist. You could do this in the Terminal with the following commands:

sudo touch /Library/LaunchDaemons/com.denyhosts.dh-daemon.plist
sudo vi /Library/LaunchDaemons/com.denyhosts.dh-daemon.plist

Give it the contents:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.hmercer.denyhosts</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/share/denyhosts/daemon-control</string>
      <string>start</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
  </dict>
</plist>

… and load it into launchctl:

sudo chown root /Library/LaunchDaemons/com.denyhosts.dh-daemon.plist
sudo launchctl load /Library/LaunchDaemons/com.denyhosts.dh-daemon.plist

Reporting blacklisted IPs

Nazar Aziz, creator of report-hack-isp:

The real problem still remains. SSHD attacks are now on the increase and it is no longer sufficient to blacklist offenders. Ideally, any SSHD hack attempt should be blacklisted, logged and most importantly; the ISP of the attacker must be notified in order to disconnect the attacking machine from the internet.

I’ve had this script running on one of my dedicated boxes for the last 12 hours and since then have received half a dozen emails from various ISPs confirming that the attacker’s servers were identified and cut off from the Internet. WIN.

Today, over 1,000,000 unique hosts have been denied by DenyHosts1. report-hack-isp is a DenyHosts plugin that will lookup the attacker’s ISP details and send an abuse report containing an excerpt of the SSHD logfile relevant to the attack. I’m now going to walk through installing this plugin, feel free to skip this section.

First, download the plugin, and extract it. Then enter the following command into the terminal, replacing <report-hack-isp-directory> with the directory you unarchived (just drag it in):

cd <report-hack-isp-directory>
sudo mv notify_isp.rb /etc/denyhosts/plugins/notify_isp.rb

Edit notify_isp.rb and replace SMTP_SERVER and SMTP_PORT with your email server’s details. Replace EMAIL_FROM with your own email address. Change LOG_FILE = ‘/var/log/sshd/**’ to your actual SSHD log file location (on a Mac it’s /var/log/secure.log). You can customise the email message in the function def get_email_message Then create the log file with sudo touch /var/log/notify_isp.log.

Make the file executable (chmod a+x notify_isp.rb) and update denyhosts.conf, pointing PLUGIN_DENY to your script. If you’re using my example DenyHosts configuration, just uncomment line 391. Restart DenyHosts and you’re done:

sudo /usr/share/denyhosts/daemon-control stop
sudo /usr/share/denyhosts/daemon-control start

Using a key pair instead of a password

To heighten SSH security, use a key pair instead of a password. This makes hacking into your server much tougher for the bad guys.

On the local machine

To get started, run ssh-keygen -t rsa on the local machine. Accept the default path and enter a password (this can be saved in the keychain). Next, go to Finder, and from the “Go” menu, select “Go to Folder…”. Enter “~/.ssh”. Copy the file id_rsa.pub.

On the remote machine

Now, on the remote machine, run touch .ssh/authorized_keys. Paste the contents of the id_rsa.pub file into this file.

Log into the remote machine as normal, and on the request for the password, type the password you entered to generate the public key. After the first login, you won’t have to type a password again.

Only allowing public key authentication

To disable password authentication and only allow public key authentication, boosting your security further, edit the file /etc/sshd_config. Find the line with the option PasswordAuthentication and, making sure it is uncommented, change it to PasswordAuthentication no. Next, find the line with the option ChallengeResponseAuthentication and, making sure it is not commented, replace it with ChallengeResponseAuthentication no. Finally, restart SSHD. This can be done on a Mac by going to the Sharing section of System Preferences and turning Remote Login off then on.

I hope this post has helped you secure your computer further. If you have any further thoughts or comments, you can get in touch with me using the comment button below.