Observations on software: from "State of the Nation" to nitty-gritty technical details.

2010/03/29

Caching ssh private keys using openssh on GNU/Linux

You probably use ssh on a daily basis, I know I do.  I find that many people I talk to don't know that typical ssh installations have the ability to cache their private keys, so they wind up having to type their private key passphrase several times a day.  Some people actually get frustrated enough with this process that they remove the passphrase from their private key file entirely.  Don't do that!  Trust me, there is a safer and better way.

In this article I discuss how to setup GNU/Linux (using openssh) hosts to cache your private keys on startup.  I will discuss how to configure Microsoft Windows hosts using Simon Tatham's excellent PuTTY applications in another article.

I set up my more secured environments (from which I ssh to any other machine I require) so that my passphrases are cached in memory using the ssh-agent daemon.  Here is what my .bash_profile runs every time I log into my primary GNU/Linux machine.

run_ssh_agent="${HOME}/.ssh/agent-for-${HOST}.pid"
[ -f "$run_ssh_agent" ] && . "$run_ssh_agent" > /dev/null 2>&1
if kill -0 $SSH_AGENT_PID > /dev/null 2>&1
then echo Agent pid $SSH_AGENT_PID
else
    ssh-agent -s > "$run_ssh_agent"
    . "$run_ssh_agent"
    ssh-add
fi
ssh-add -l

This bash script (backwards compatable to sh) starts up and installs your private keys into the ssh-agent daemon.  Every time you login to this machine thereafter your shell is configured to use the same agent as before, so you don't need to retype your passphrase until either the daemon is killed or the machine is restarted.

How it works:

Note that the run_ssh_agent shell variable references a host specific file.  This file is used to retain shell settings required to contact the ssh-agent key server so that they are accessible across multiple login sessions.  We now load these settings and check to see if the ssh-agent key server daemon has already been started using the kill -0 $SSH_AGENT_PID command.

The special environment variables that ssh applications (i.e., ssh, scp, sftp) require from your shell include SSH_AUTH_SOCK and SSH_AGENT_PID. The first references a FIFO located in a secured directory (normally in /tmp) and the second indicates the process identifier of the agent.  The ssh applications use the former when use of the private key is required, typically passing the actual authentication work off to the ssh-agent.  This script uses the PID variable to determine whether or not the agent is running.

The program ssh-agent is a daemon that stores your private keys on behalf of other ssh applications.  The -s option to ssh-agent tells it to dump to STDOUT a script that sets up the above named environment variables for Bourne compatible shells (i.e., bash) and the following line then tells the running shell to evaluates the just-generated script. This loads the SSH_* environment variables into the running shell.

The ssh-add application is then executed. The job of ssh-add is to perform user authentication via the passphrase attached to each private key when it was generated, and then load each corresponding key into the ssh-agent daemon. Finally, after everything has been started or installed the ssh-add -l command is executed to list each identity found in the key server.

After installing the above code in your .profile or .bash_profile you should see something like this the first time you login or run bash -login.

Agent pid 22535
Enter passphrase for /home/kevin/.ssh/id_rsa:
Identity added: /home/kevin/.ssh/id_rsa (/home/kevin/.ssh/id_rsa)
Identity added: /home/kevin/.ssh/id_dsa (/home/kevin/.ssh/id_dsa)
Identity added: /home/kevin/.ssh/identity (kevin@linux)
3072 bb:55:6d:a0:b9:c6:c9:10:03:72:9e:e4:cf:3b:a4:44 kevin@linux (RSA1)
3072 64:42:98:8f:05:8c:a5:df:52:fa:6a:d0:fd:5a:78:bd /home/kevin/.ssh/id_rsa (RSA)
3072 cf:05:ae:d6:91:c0:9b:ce:03:81:88:35:f2:af:c6:49 /home/kevin/.ssh/id_dsa (DSA)

The ssh-add application will prompt for a passphrase for each identity file located in your ~/.ssh directory that has a different passphrase. As you see here, I use the same passphrase on all of my ssh private key files.

Every time you login thereafter you will see something like this:

Agent pid 22535
3072 bb:55:6d:a0:b9:c6:c9:10:03:72:9e:e4:cf:3b:a4:44 kevin@linux (RSA1)
3072 64:42:98:8f:05:8c:a5:df:52:fa:6a:d0:fd:5a:78:bd /home/kevin/.ssh/id_rsa (RSA)
3072 cf:05:ae:d6:91:c0:9b:ce:03:81:88:35:f2:af:c6:49 /home/kevin/.ssh/id_dsa (DSA)

You can now take advantage of these private keys by distributing an associated public key to whom you please. Configure one in your Subversion server so you can use the svn+ssh scheme. Add one to your normal remote machines.

2 comments:

  1. Its okay that it saves time for you to type pass phrase several times a day.But is it secure if you cache it.Will it not loose the whole purpose of this keypair mechanism.How long the cache will be maintained or we also have control over that?

    ReplyDelete