Five Minutes to a More Secure SSH


Here is a quick way to drastically improve the security of your OpenSSH server installations. Apart from past flaws in the OpenSSH daemon itself that have allowed remote compromise (very rare), most break-ins result from successful brute-force attacks. You can see them in your firewall, system or auth logs, they are an extremely common form of attack. Here is an excerpt from the /var/log/messages file on a CentOS Linux box (the attacking hostname has been obfuscated). You can see multiple attempts to login as users root and ftp. Also note the time between repeated attempts - one second or less, much too quick to be a human. This is an automated attack.

Apr  9 09:34:51 server1 sshd(pam_unix)[1511]: authentication failure; logname= uid=0 euid=0 tty=NODEVssh ruser=
Apr  9 09:34:52 server1 sshd(pam_unix)[1513]: check pass; user unknown
Apr  9 09:34:52 server1 sshd(pam_unix)[1513]: authentication failure; logname= uid=0 euid=0 tty=NODEVssh ruser=
Apr  9 09:34:53 server1 sshd(pam_unix)[1515]: authentication failure; logname= uid=0 euid=0 tty=NODEVssh ruser=  user=ftp
Apr  9 09:34:53 server1 sshd(pam_unix)[1517]: check pass; user unknown
Apr  9 09:34:53 server1 sshd(pam_unix)[1517]: authentication failure; logname= uid=0 euid=0 tty=NODEVssh ruser=
Apr  9 09:34:54 server1 sshd(pam_unix)[1519]: authentication failure; logname= uid=0 euid=0 tty=NODEVssh ruser=  user=root
Apr  9 09:34:55 server1 sshd(pam_unix)[1521]: check pass; user unknown
Apr  9 09:34:55 server1 sshd(pam_unix)[1521]: authentication failure; logname= uid=0 euid=0 tty=NODEVssh ruser=
Apr  9 09:34:56 server1 sshd(pam_unix)[1523]: check pass; user unknown
Apr  9 09:34:56 server1 sshd(pam_unix)[1523]: authentication failure; logname= uid=0 euid=0 tty=NODEVssh ruser=

From personal experience with clients over the years, I have found that most administrators tend to install an SSH server and leave it at its default settings, typically to allow password authentication and root logins. Many don't even know that there is an alternative (key-based authentication), or they think the alternative is too hard to use. It is not - it takes all of five minutes to configure key-based authentication and disable root logins, and the security gains are enormous. Below, I'll step you through the process.

Configuring and Testing Key-Based Authentication

This is not really a hard as it seems. By default, all recent OpenSSH configurations allow public key authentication. You just have to generate a pair of SSH keys on the client, and append the generated public key to a file named authorized_keys on the server. This works on any Unix/Linux with OpenSSH, or even under Windows with Cygwin's OpenSSH port (I won't mention it further here, but If you are stuck on a Windows client without Cygwin, use PuTTY and check out Using PuTTYgen).

Let's say you routinely use SSH to login from your home workstation, sshclient, as user obiwan, to a remote SSH server as user vader. For consistency's sake, we'll call the remote server sshserver. I'm assuming you have working password authentication already.

On sshclient, log in under your user account obiwan, and run the following three commands.

obiwan@sshclient:~$ ssh-keygen -t dsa
This first command generates the public/private key pair for you, assigns a passphrase to the private key, and stores both keys in the directory ~/.ssh by default. Just accept the defaults, and enter a passphrase when prompted.

 obiwan@sshclient:~$ cat ~/.ssh/ | ssh vader@sshserver 'cat >> .ssh/authorized_keys'

or, you can simply use the 'ssh-copy-id' command:

 obiwan@sshclient:~$ ssh-copy-id vader@sshserver

This command appends your public key, which is stored in ~/.ssh/ by default, to the authorized_keys file on the remote host. One caveat, you may not have a '.ssh' directory on the remote server in vader's home directory. Create it if needed.

 obiwan@sshclient:~$ ssh vader@sshserver chmod 600 .ssh/authorized_keys

This last command changes the permissions on the remote authorized_keys file to be more secure, and to prevent a common problem that prevents key-based authentication.

Now, test SSH login to 'vader@sshserver'. You should be prompted for a passphrase this time, not a password. Enter the passphrase you chose when you created your keys, and you should be logged in.

Disabling Password Authentication

Once key-based logins are working, disable password authentication. Find your SSH server's configuration file. This is usually in /etc/ssh/sshd_config. Find the line that says:

PasswordAuthentication yes

and change it to

PasswordAuthentication no

You should also disable challenge-response authentication, in case your version of OpenSSH is using PAM to authenticate (see below for an explanation):

ChallengeResponseAuthentication no

Disabling Root-Logins

Finally, disable root logins. Kudos go to NetBSD and FreeBSD, whose default configurations do not allow root logins, so there will be nothing to do for you to do in this step if you are using a recent version of either one. OpenBSD and most Linux distributions allow root logins by default. Again in /etc/ssh/sshd_config, find the line that reads

PermitRootLogin yes

and change it to

PermitRootLogin no

Reload your SSH server's configuration with /etc/init.d/ssh reload (sysvinit Linux), /etc/rc.d/rc.sshd reload (Slackware Linux), systemctl reload sshd (systemd Linux), /etc/rc.d/sshd reload (NetBSD/FreeBSD/OpenBSD) or just send sshd a HUP signal, usually with something like kill -HUP pid, where pid is the process ID of the SSH server, you can get it quickly on any Unix platform by running something like ps ax | grep sshd.

Details on PAM Authentication

Disabling PAM-based password authentication is rather un-intuitive. It is needed on pretty much all GNU/Linux distributions (with the notable exception of Slackware), along with FreeBSD. If you're not careful, you can have PasswordAuthentication set to 'no' and still login with just a password through PAM authentication. It turns out that you need to set 'ChallengeResponseAuthentication' to 'no' in order to truly disable PAM authentication. The FreeBSD man pages have this to say, which may help to clarify the situation a bit:

Note that if ChallengeResponseAuthentication is 'yes', and the PAM authentication policy for sshd includes pam_unix(8), password authentication will be allowed through the challenge-response mechanism regardless of the value of PasswordAuthentication.

Common Objections

Many sysadmins advocate leaving password authentication in place, and mandate the use of strong passwords. This is an example of 'shallow defense', and is a bad idea for a few reasons. First, even if you pick a password strong enough to make brute-force attacks next to impossible, you are still relying on a single authentication factor. Depending on your circumstances, you should take into account non-brute force methods of attack that may compromise passwords, like social engineering or exploiting weaknesses in underlying authentication algorithms. Again, this depends on your circumstances. If you are the only SSH user and are willing to accept the risks of password authentication, it may work fine for you. The idea of not relying on a single authentication method, applying defense in depth whenever possible, underlies the idea of using two-factor (keys + passphrases) authentication.

Another common recommendation is to leave OpenSSH in its default state (using password authentication), and use a tool like Denyhosts. I've never been a big fan of methods like this, I think using the security features present in OpenSSH itself makes for a simpler and cleaner solution. I'm also very wary of any tool that automates the blocking of network connections.

Closing Thoughts

There is much more to OpenSSH configuration and security, but these few, simple steps will go a long way towards preventing brute-force attacks and letting you sleep at night. Repeat the above steps on all your SSH servers, copying your SSH public key to each server as needed (it may not be obvious if you've never used key-based authentication before, but don't regenerate your keys for each host).

More Information