Gecko-AK.org Networking/Security Reference Pages


How to Use SSH Pubkey Authentication to Enhance Server Security

The Plan

By default, when a user uses SSH to connect to a remote server, SSH authenticates the user by requesting a user name and a password from the user, then comparing these values with /etc/shadow (on systems using shadowed passwords). If there is a match, then SSH allows access to the server. This is, of course, an oversimplification, but is the basic idea behind how SSH typically authenticates a user. However, SSH also allows users to create DSA or RSA keys to use for authentication instead of passwords. This is sometimes used to create "SSH trusts" between servers so that users (often root) can transfer data or commands in scripts without requiring the user to know the root password on each server. Obviously, there are security compromises with allowing root SSH trusts between servers, so this should only be done if you are really sure you know what you are doing.

However, SSH Pubkey authentication can also be used to enhance security. The same technique that can replace user name/password authentication in the SSH trust described above can also be used with a password to authenticate a user. There are some caveats to this technique, as well, however. If you change your password on the remote server, you will still be using the same old password to authenticate with SSH, since the SSH password is now tied to your public keys, rather than /etc/shadow.

However, this can be a good thing. Suppose your user account has sudo permissions on the remote server, and you are authenticating from /etc/shadow rather than using Pubkey authentication. If someone compromises your password, either by shoulder surfing while you log in, brute force trial and error, or through a password cracking program, then the cracker now "owns" your account on the remote server--(s)he can do anything you can do, because your account uses only one password for logins, sudo access, etc. Suppose, on the other hand, that you are using SSH Pubkey Authentication with a password that is different than your system password in /etc/shadow. If the cracker obtains your SSH password, (s)he must still have the SSH key to sign in to the server, and even then, the cracker cannot run any sudo commands with your account until/unless (s)he cracks your shadowed password as well. On the other hand, if the cracker obtains your shadowed password, but not your SSH password, then (s)he must find another way to gain console access to the server, such as via telnet, or through physical access to the server. Now, your account is more secure than it was with just shadowed passwords, since the cracker must crack two passwords to do anything useful with your account.

Howto: Let's get to it!

So, you are sold on the concept, and now you want to set it up on your servers. There are a few things you must do first. I am going to assume that you are only using the SSHv2 protocol. If you aren't, you should be, so go fix it right now! I'll wait until you get back <grin>

First, edit your sshd_config file on the SSH server to allow SSHv2 Pubkey Authetication:

        PubkeyAuthentication yes
      

and make a note of where sshd is looking for your authorized keys to be placed:

        #Looks in the user's $HOME/.ssh/authorized_keys file
        AuthorizedKeysFile     .ssh/authorized_keys
      

When convenient (i.e., when you have some other method of gaining a login to the server, like physical access, console via serial cable or telnet), restart sshd so that the changes to sshd_config will be read.

Next, use the ssh-keygen program to create your public (server) and private (workstation) keys. There are two types of keys that you can create with SSHv2: DSA keys and RSA keys (actually, since you create public and private keys with both encryption algorithms, I suppose there are actually four keys that you can create, but you get my point). At the time I wrote this article, I had not done enough research to know the relative strengths of DSA vs. RSA, so I am not going to recommend one over the other. Pick whichever one you think is best :) I am going to pick RSA for purposes of this document, but do not stake your network's security on the fact that I chose RSA when writing this document.

Once again: I am picking RSA for this document just because. Do your own homework before choosing one encryption scheme over another. I will not be held liable if your network is compromised because you were not willing to research the merits of one encryption scheme over the other!

Now that you have done your homework, and selected either RSA or DSA to encrypt your keys (did I mention that you should research this before picking one?) generate your keys like this:

        ssh-keygen -t rsa
      

You may also use the -b flag to specify the number of bits to use in the encryption scheme, if you feel so inclined. The default is 1024, but the ssh-keygen manpage didn't give the max that you can specify :( (or at least, I didn't see it).

The ssh-keygen program will prompt you for a passphrase and a location in which to store the keys. The default is $HOME/.ssh/. If you created RSA keys, you should see the following files in $HOME/.ssh/:

        $ls ~/.ssh/
        id_rsa  id_rsa.pub  known_hosts
        $
      

id_rsa is your private key, and should be kept, well, private. id_rsa.pub is the public key that you will need to copy to your SSH server, so let's do that now. Use SCP, FTP, copy/paste, NFS, etc. to copy id_rsa.pub to the SSH server, then edit (or create and edit, if needed) the authorized_keys file in $HOME/.ssh/ on the ssh server. For example, assuming that I copied the file id_rsa to $HOME on the SSH server, run the following commands:

        #make sure that the .ssh directory exists in your home directory:
        $ls -ld .ssh
        drwx------    2 foo     users        4096 Aug 24  2004 /usr/home/foo/.ssh/
        $
        #if you get the error message "ls: /usr/home/foo/.ssh: No such file or directory, do this:
        $mkdir /usr/home/foo/.ssh
        #Now, append id_rsa.pub to the authorized_keys file:
        $cat ./id_rsa.pub >> .ssh/authorized_keys
        #...and set the permissions so only the user can read the authorized keys file:
        $chmod 600 ./ssh/authorized_keys
      

The next time you log into your SSH server, your familiar "user@hostname's password:" prompt should be replaced with "Enter passphrase for key '/usr/home/username/.ssh/id_rsa':". If you repeat this process (from the copy to the ssh server) on any other SSH servers in your network, you can set up Pubkey authentication on them. That's all there is to it! As long as your SSH Pubkey passphrase is different than your logon password, crackers will have to break two passwords to do anything that requires sudo permissions with your account, thus increasing security in your network.