David Findlay

a man, a plan, a cake: nirvana

SSH Public Key Authentication

RapidWeaver 3.6.3 just came out, which is the web site publishing application that I use. One of the new features they've added is support for SSH public key authentication for publishing changes to a site to your web server. This reminded me that I've been meaning to post a quick how-to on this under-appreciated feature of SSH. So here goes.

Back in the day we all used TELNET to connect to our servers. This was fine until bad people came along. TELNET sends your username and password in the clear, and so bad people started watching packets fly past and grabbed your account information out of the air. And then came Secure Shell, or SSH, which uses secure sockets technology to encrypt the connection between your client and server machines. No more password grabbing.

By default you use SSH pretty much like TELNET, where you specify your username and password every time you connect. However, SSH also supports public key authentication, which allows you to securely not have to enter your username and password every time you connect. Yes, this sounds counterintuitive but it's true.

What follows is a super-quick how-to. If you want more specifics check out Dave Aaldering's SSH with Keys HOWTO or the various man pages for ssh (try man -k ssh to see what man pages your system has for SSH).

To configure anything for SSH you need to create SSH's configuration directory, if you don't already have it. On your client and server:
mkdir ~/.ssh
chmod 700 ~/.ssh


The chmod is so only your user account has access to the SSH configuration directory. That's important. Once you have done that, you can proceed to creating your key. On your client:
cd ~/.ssh
ssh-keygen -t dsa

Accept all the defaults and specify a blank keyphrase when asked. You can include a passphrase, in which case the server will prompt you for this passphrase each time you connect. I'm assuming you want to skip that step, but feel free to specify a passphrase if you wish. The advantage is not specifying one is convenience. The disadvantage is that anyone with access to the console on your client machine will be able to access your server without a password.

You should now have a public key in ~/.ssh/id_dsa.pub and a private key at ~/.ssh/id_dsa. The public key needs to go on your server. The private key needs to stay where it is (this is what identifies you to the server and lets you log in without needing to specify a password). You may want to backup the private key file, since if you lose it you'll have to go through these steps all over again.

Transfer your newly-created ~/.ssh/id_dsa.pub public key file to the same directory on your server. Then on your server:
cd ~/.ssh
cat id_dsa.pub >> authorized_keys
chmod 600 authorized_keys
rm id_dsa.pub


This tells the SSH daemon on your server that you authorize clients that know the private key that goes with this public key. The >> appends to authorized_keys if it already exists: you authorize as many clients as you wish (one for your laptop, one for your home desktop machine, etc.).

Now that you've told the server it's okay for your client to connect using a key, try it out. On your client:
ssh server-username@server-ip

You should be logged in without being prompted for a password! If not, make sure that ~/.ssh has permissions of 700 and ~/.ssh/authorized_keys is 600. You may also need to tweak your server's SSH daemon configuration file. It's usually at /etc/sshd_config and the entry you want is PubkeyAuthentication yes.

Once you have it working, if you want to disable log ins with a password, so that you can only do it with your key, set PasswordAuthentication in /etc/sshd_config to no. Be sure you don't lose that private key once you've done this though!

Extra Credit

If your username is different on your client than on your server then create ~/.ssh/config on your client and add an entry like the following:

Server server-name-or-ip
User your-server-username


You can also add Port and Hostname entries for your server which can be convenient if you want to refer to the host by a different name when connecting (or if it a name if it doesn't have a DNS entry), or if the port is not the usual 22 and you don't want to remember to have to use the -p option to the ssh command. See man ssh_config for all the details.