More Secure AND More Convenient: Secure Shell keys and agents everywhere you go

As security increases, convenience tends to decrease. But in this case we gain some of both.


Problem 1: Brute force SSH attackers

I recently made a Linux machine accessible by port 22 from the Internet, so I could remotely administer it with SSH. Within a day or two, there were hosts from all over the Internet trying to log in using random usernames (‘root’, ‘dave’, ‘mysql’, ‘neo’) and random passwords.

Problem 2: Weak system passwords

System passwords are becoming easier to guess by brute force every time a new processor comes out. It doesn’t matter how complicated your alphabet soup is, it’s just not long enough, or won’t be long enough eventually. The bad guys also have botnets full of machines and all the time in the world.

Working around problems 1 and 2: Key authentication

An SSH key is complex (random) and much, much longer than your password (see Wikipedia for more details about how public-key cryptography works). You store the private part of your key securely on your client machine, and tell the server to trust only the public key that goes with it. BUT, you should really use a nice, long, complex passphrase to lock up your private key so that someone who gains access to it can’t get free access to all your servers, which leads to

Problem 3: I’m too lazy to unlock my inconvenient SSH key all the time

I log in to different machines all the time, from a bunch of different workstations. But, I have a long passphrase on my SSH key. Too long to type every time, especially if I’m just looking at something or transferring a file or two.

Solution to problem 3: A key agent

An SSH key agent lets you unlock your key and load it into memory once, and then automatically uses it to get you in to all your servers. SUPER convenient.

Problem 4: It’s confusing

I tried to explain it to a friend recently and found nowhere on the internets that explained it all in one place.

Coming up: detailed instructions for getting started with SSH keys and using a key agent on Mac OS X (command line), Windows (PuTTY and Cygwin commandline ssh), and Linux/Unix (command line).



Generate your key with a command-line (Open)SSH client (Cygwin, Mac OS X, Linux)

I’m going to start with this client, because the command-line OpenSSH is the common denominator on all the OSes I use.

  1. Write down a nice long, complex, memorable passphrase that you’re capable of typing reliably, and store it in a safe place. You probably won’t need it every day (unless you reboot a lot), so make sure you can remember and type it. Security expert Bruce Schneier suggests a scrap of paper in your wallet is a pretty good place.

  2. Generate a private key with ssh-keygen from your client machine’s command line:

$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/myusername/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):     # use yours from step 1
Enter same passphrase again:
Your identification has been saved in /home/myusername/.ssh/id_rsa.
Your public key has been saved in /home/myusername/.ssh/
The key fingerprint is:
9a:89:9c:6b:87:a7:e8:93:9a:f5:f7:35:bf:23:87:c6 myusername@myhostname
  1. The file permissions of your new .ssh directory and the files in it (except maybe your public key) should be very restrictive, allowing only you to read them. But just in case, reset them restrictively:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/*
chmod 644 ~/.ssh/
  1. You need to append your public key to ~/.ssh/authorized_keys on each of your servers:
    • if you don’t have an authorized_keys file in your ~/.ssh directory, just copy your public key to it on each server:
scp -r ~/.ssh/  myserver:.ssh/authorized_keys
  • if you already have one, you’ll need to append your key to it. Use a text editor and paste, copy and paste, or, courtesy of CodeSnippets,
cat .ssh/ | ssh user@domain.tld 'cat >> .ssh/authorized_keys'
  1. Test and make sure it works! When you ssh to the server, it should prompt you for your passphrase to unlock your private key, and then you should successfully connect. Using the -d flag to ssh gives you verbose debugging information which is usually useful.
$ ssh -v myserver
... # copious debug information about which keys or 
... # authentication methods ssh is trying ]
Enter passphrase for key '~/.ssh/id_rsa':
... # here's where you type your passphrase correctly
... # more debugging
debug1: Entering interactive session.
Last login: Thu May 21 14:30:31 2009 from
  1. I like to turn on agent forwarding by adding this line to ~/.ssh/config file on each server. This allows you to ssh from server A to another server B that trusts your key, using the agent on your client machine to pass your key through. ForwardAgent yes

  2. If all the users on the server will be using keys from now on, it’s a good idea to turn off password authentication for the whole server, in sshd_config, which is usually located in /etc/: PasswordAuthentication no Unfortunately, I can’t figure out how to lock one account on the server from using password authentication. You can put that line in your ~/.ssh/config file, but it only affects your use of ssh from that account, not to it.

Or, generate your key with PuTTY on Windows:

PuTTY is rock-solid terminal and SSH software for Windows. I usually generate my key with the command-line OpenSSH tools and then import it to PuTTY, but here’s how you do it the other way around:

  1. Install the latest version of the whole PuTTY package. At the time of this writing, the PuTTY author’s site has been inaccessible for a while, but there are mirrors available for downloading the software.

  2. Generate an RSA key with puttygen.exe, using a good passphrase (see instructions in the PuTTY manual chapter 8)

    Generating a key with puttygen.exe

    Generating a key with puttygen.exe

  3. Save the private key somewhere using the ‘Save private key’ button, like maybe in C:\Documents and Settings\yourusername\.ssh\puttyprivkey to be compatible with command-line SSH tools. Save the public key somewhere too (though you will paste it, below).

  4. Make the file permissions of that directory and the files in it very restrictive (only you should have access).

  5. On one server, edit .ssh/authorized_keys in your home directory (creating it if it doesn’t exist yet), and paste your public key from puttygen in there

  6. Test that it works! Tell PuTTY to try key authentication instead of password authentication by setting your private key under Connection->SSH->Auth in the connection settings:

    Tell PuTTY to use your key

    Tell PuTTY to use your key

  7. Copy the authorized_keys file and/or the whole .ssh directory to each other server. Eg on the first server, scp -r .ssh myotherserver:

  8. Turn on agent forwarding (and “try to use Pageant”… see screenshot above) for each ssh session config in PuTTY in the Connection->SSH->Auth pane (this lets you ssh from server A to another server using the agent on your client machine)

  9. Put your username in the “Auto-login username” field under Connection->Data for each saved PuTTY session:

    Don't forget to fill in the Auto-login username field for each saved PuTTY session.

    Don't forget to fill in the Auto-login username field for each saved PuTTY session.

Using your PuTTY key with command-line ssh client (Cygwin, Mac OS X, Linux):

If you want to use the key you just generated with puttygen.exe with another ssh client (eg cygwin commandline ssh), export your private key from puttygen and store it in your .ssh dir (ssh looks by default for .ssh/id_rsa but these instructions let you specify another name), and put these lines in your .ssh/config file:

ForwardAgent yes
IdentityFile ~/.ssh/id_rsa_putty_priv.openssh

( i.e., the filename of your exported private key )

To change your ssh key password

Load it in puttygen and change the password, save and export it for your other ssh client(s) if necessary

Using a different key from home or another machine or whatever

You can copy your private key to several machines, or you can generate a new key on each and append the public key to the .ssh/authorized_keys file on the server. Think about how much you want to expose/replace if something gets compromised.

In my case, I use one private key on all my client computers at work, one on my home computers, and one on my Palm handheld. That way if one of my client computers is lost, stolen or compromised, I can disallow that key but keep the others.


So far, we’ve made SSH more secure, but my key passphrase is at least as much of a pain as using my password — in fact, more so because it’s about twice as long.

Using an SSH Key Agent offers a killer mix of security and convenience. When you open the agent and load your keys, you can unlock them and they’re held unlocked in memory. This lets you open connections all day without having to type your password or passphrase. NOTE WELL, lock your machine when it is unattended if you have an agent running; otherwise anyone who walks up to it can conceivably log in to any of the servers you’ve configured to trust your key.

To use PuTTY’s agent “Pageant” on Windows:

  1. Launch pageant.exe, PuTTY’s ssh agent, right-click it in the system tray, and add your private key.

Now you can log into all your servers conveniently and get from server to server using agent forwarding.

You may want to convince pageant.exe to run at login. See Chapter 9 of the PuTTY manual.

I just made a shortcut to pageant and edited the Target to load the key and launch PuTTY at startup thusly: "C:\Program Files\putty\pageant.exe" "C:\Documents and Settings\myusername.ssh\puttyprivkey.ppk" -c "C:\Program Files\PuTTY\putty.exe"

To run an agent with the command-line OpenSSH client:

This applies to Linux, Mac OS X, and Cygwin.

Basically, add this line to your .profile file in your home directory, to start the agent whenever you open a shell:

eval `ssh-agent -s`

Then, before you ssh to anything in that terminal, use the ssh-add command (if your private key in openssh format is named .ssh/id_rsa) or ssh-add ~/.ssh/puttyprivkey.openssh if you’ve got a weirdly named one you made with puttygen.exe, above.

$ ssh-add
Enter passphrase for /cygdrive/c/Documents and Settings/myusername/.ssh/id_rsa:
Identity added: /cygdrive/c/Documents and Settings/myusername/.ssh/id_rsa (/cygdrive/c/Documents and Settings/myusername/.ssh/id_rsa)

ssh-add -l (ell) shows which keys the agent is currently holding.

$ ssh-add -l
9a:89:9c:6b:87:a7:e8:93:9a:f5:f7:35:bf:23:87:c6 /cygdrive/c/Documents and Settings/myusername/.ssh/id_rsa (RSA)

Making it nicer in with keychain

The keychain utility you can get with Cygwin (and some Linuxes) is also nice. I put this line in my .bashrc so that every Cygwin shell either starts the ssh agent or connects to the already running one.

eval `keychain --eval -q -Q --noask`

Then I can use ssh-add (see above) when I want to load my keyring, and all my open Cygwin shells get it, until I log out or restart Windows.

Running an agent on Mac OS X

In Leopard (Mac OS X 10.5, released in October 2007), the SSH Agent is integrated into the OS, so if you’ve generated your keys with ssh-keygen as above and they live in ~/.ssh/id_rsa and, you will get prompted to unlock your key the first time you try to ssh or scp anywhere:

This dialog box prompts you to unlock your key and/or start the agent.

This dialog box prompts you to unlock your key and/or start the agent.

The “Remember password in my keychain” checkbox makes it keep an ssh agent running. It works great.

For older versions of Mac OS, you want SSHKeychain. It also works with the Apple Keychain, to remember your key’s passphrase.

Both solutions work seamlessly for all the OpenSSH tools (ssh, sftp, scp, etc) in all your terminals.