Using SSH Passphrases

From LSDevLinux
Jump to: navigation, search

We use ssh a lot, especially for access to our source code repository (currently CVS). We use a public key system with ssh, and most of our server accounts don't have a password at all; they can be accessed only with a key.

For security, we ask people to protect their key with a passphrase. However, it is very inconvenient to have to type in the passphrase on every single access to the repository. The solution to this is to use an ssh agent, but finding out the best way to do this isn't all that clear from the documentation.

On most Linux systems, the ssh-agent program will already be running when you log into a graphical session. However, it won't have any keys cached in it. To add your keys, you can type ssh-add in a terminal window. (You will, of course, be prompted for the passphrase.) From then on, ssh will use your key from the agent and not prompt you for a passphrase. You won't be asked for it again until after you log out (or you explicitly remove the key from the agent).

However, it's annoying to have to remember to do this before you use ssh. A nicer solution is to have your graphical session prompt you for your ssh passphrase immediately after you log in.

To enable this, first install an ssh-askpass program. On Debian-based systems, there are four packages that provide ssh-askpass. The one we prefer is ssh-askpass-fullscreen. If you want to play around with the four alternatives before settling on a permanent choice, you can try out each one by running it in a terminal (but don't enter your real password as it will be written to the terminal afterwards). You then use the Debian alternatives mechanism to switch the default between them (with sudo update-alternatives --config ssh-askpass in a terminal).

However, you also need to arrange for the key-adding operation to take place at login. The simplest option is to create a file ~/.Xsession as follows:

exec x-session-manager

This will cause ssh-add to be run just before continuing with the normal session process.

It's also possible to have ssh-agent, and therefore your cached keys, last across logins. For this, you need to use the keychain program (found in the Debian package of the same name). Instead of using ssh-add in your ~/.Xsession, you can use the following:

eval $(keychain --eval --noinherit id_dsa)
exec x-session-manager

keychain will look for a previously-existing agent and attach to it. It will then add the id id_dsa to it. The agent that keychain starts, and the keys added to it, will persist after logout.

It's also possible to have keychain work in a text login (including a remote login via ssh!). For this, you need to invoke it in your ~/.bash_profile (or equivalent, for other shells). Rather than duplicating the code for calling keychain, it's tidier to have your .bash_profile executed as part of your X session startup.

To do this, I removed ~/.Xsession and created a ~/.gnomerc as follows:

. .bash_profile

On my system (Debian Etch) ~/.gnomerc is run before the default ssh-agent, which simplifies things slightly. I assume that KDE would be similar.

I then edited my ~/.bash_profile to contain a block like this:

if [ -z "$SSH_AUTH_SOCK" -a -x "$(which keychain)" ]
    keychain id_dsa
    [ -f $HOME/.keychain/$HOSTNAME-sh ] && \
       . $HOME/.keychain/$HOSTNAME-sh
    [ -f $HOME/.keychain/$HOSTNAME-sh-gpg ] && \
       . $HOME/.keychain/$HOSTNAME-sh-gpg

This checks that the session doesn't already have an agent set up (in case you are using agent forwarding), and that you have the keychain program installed, then runs the host-specific scripts that keychain creates (as an alternative to using --eval). So now keychain will search for an existing agent and add my key to it from both text and graphical logins.

In addition, all the code in my .bash_profile will be executed in a graphical login. This means that I set things like environment variables in .bash_profile rather than .bashrc, which is really how these files are designed to work.

If you're curious about the details of how ssh-agent works, the short explanation is as follows. The X11 session mechanism already runs your session under the control of ssh-agent (see /etc/X11/Xsession.options and /etc/X11/Xsession.d/*ssh-agent). However, there is no automatic action to add keys to the agent. In other words, ssh-add has to be explicitly invoked. Also, without an ssh-askpass available, ssh-add has no way to prompt you for a passphrase and thus add your key to its cache.

Once a key is placed in the cache, programs can request them from the agent via a socket. They gather the necessary details for contacting the agent from environment variables that ssh-agent sets up. This is why the whole session is run as a subprocess of the agent, so that all programs will inherit the appropriate environment variables.