The secure shell software, SSH, is usually configured to prompt users for a password when they try to establish a connection to an SSH server. However, there are many circumstances when this presents problems - writing automated system maintenance scripts, for example. Using SSH keys, it is possible to configure SSH and its related commands to allow connections without user intervention.

Getting started with keys and agents

The first thing you should understand before following any of these instructions is that it is not secure to use the client-side tools (keychain, ssh-add, or ssh-agent) on machines where you do not trust all the users, especially anyone who has root access. It is possible for root to use your ssh-agent to login as you on all machines to which you have access. You can connect to machines where you don't trust all the users, including the root user, because only your public key is installed on those machines.

SSH uses public-key cryptography. This means that connections between two machines are secured using a public and private key. Data encrypted with one can only be decrypted with the other. When using SSH, your public key is passed to the remote system and you keep your private key is held on the local system.

So, in order to log into a machine without a password, you must first generate a new keypair using ssh-keygen. You will be asked to enter a passphrase. This is used to protect your private key so that it is unusable without the correct phrase. You should not simply leave the passphrase blank. (If you do so, the key is highly insecure, and anyone who gets access to the file containing the key can use it. There are however some circumstances in which passphrase-less keys are the most practical solution as they can be set up for use with only a single command on a remote system.) ssh-keygen produces a public and a private key in ~/.ssh.

Next, you should copy your public key to the remote system. Copy it into the ~/.ssh directory on the remote system, ensuring that it has a unique name and won't overwrite any existing data. Once you've copied the key over, you need to tell the remote system to trust connections using that key, so add the key to authorized_keys file. From within ~/.ssh, a simple

cat mynewkey.pub >> authorized_keys

OK, so you should now be able to connect to the remote machine without it prompting you for a password. However, you'll still be asked for your passphrase when you access the private key stored on your machine. So you've not actually (yet) saved any effort when connecting to a single remote machine. (If you configure multiple remote machines to trust your public key, then you only have to remember your single passphrase rather than multiple passwords for the remote systems. This is more secure than setting the password on all those remote systems to the same value.)

In order to get round the problem of entering and re-entering your private key passphrase, you need to use the ssh-agent program. ssh-agent can be set to start with a new login session (using ~/.profile), but can also be started by a graphical login manager like GDM. ssh-agent stores the passphrase for your private key (or keys), serving them up to SSH as necessary.

The short guide to generate a keypair and login to a machine without a password:

$ ssh-keygen -t rsa                  # Generate a keypair
$ ssh-copy-id <target machine>       # Copy to the remote machine
$ eval `ssh-agent`                   # Starts an ssh-agent
$ ssh-add                            # Add your key to the agent
$ ssh <target machine>               # Connect to the remote machine without password

The following guides explain in more detail how to generate ssh key pairs and set up ssh-agents:

The following section is incomplete ( GrahamBleach is working on it)

Sharing an ssh-agent between multiple login sessions

In some circumstances it is useful to share one ssh-agent between several login sessions. Usually this is when using a remote machine as a jumping off machine to other machines. It would of course be possible to start a new ssh-agent each time you login and then add your identity to each agent. However, this quickly becomes incredibly tedious.

Keychain is a wrapper for ssh-agent that makes the task of configuring your shells to use a single ssh-agent much simpler. It finds any ssh-agent that may be running under your userid, or starts one if there isn't one currently running, then outputs the environment variable settings that will tell ssh to use the agent.

Serving suggestion

Firstly, install keychain. If it is not supplied by your distribution then you may obtain it from the keychain homepage.

Secondly, have keychain started by your login profile. In a bourne-based shell (e.g. bash), add something like this to your .profile.

/usr/local/bin/keychain > /dev/null
. ~/.keychain/`hostname`.sh
ssh-add -l >/dev/null 2>&1 || ssh-add -t $((1*3600)) # comment out this line if you don't want to prompted for your ssh passphrase at login

This fragment of code does the following:

Now log into the machine. On the first login you should be prompted for your ssh passphrase, on subsequent logins you should not. You should be able to use your ssh key without offering a passphrase from any of them for the next hour.

Further reading

The article that introduced keychain and explained how to use it is at http://www-106.ibm.com/developerworks/linux/library/l-keyc2/

Managing ssh-agents within an X session

On an X-based desktop using a login manager, such as xdm or gdm, a different method is appropriate.

To be completed.

==== Removing your identity when the screen is locked ====

This section explains how, for added security, it is possible to remove all the keys from your agent when xscreensaver locks the screen and be prompted for the passphrase again when the screen is unlocked. In this manner, if your workstation is compromised in some way while you are away from your desk, your agent cannot be used for mischief.

This is simply done with a few lines of perl, based on the sample script in the xscreensaver-command manpage. We wait for events from xscreensaver-command -watch and run ssh-add -D if we get a LOCK or BLANK event or a ssh-add if we see an UNBLANK event. We call this script from .xsession or similar, having set $SSH_ASKPASS to the ssh-askpass program we would like to use to enter our passphrases.

To be completed and script added

Agent forwarding

To be added

SSH Keys and Cron

Jobs run in a user crontab do not inherit any of environment variables that are set up for your login session. This makes using SSH keys with commands run by cron a bit more difficult - the commands don't know how to contact your ssh-agent. If you want to run backups or similar using your crontab and are already logged in, you use a wrapper script to get passwordless authentication working. It assumes that you have added your key to ssh-agent using the ssh-add command. You need to help the command get the SSH_AUTH_SOCK environment variable from your login shell. To do this, run the following as a wrapper around your cron command (or simply insert the lines at the end of your script if it is a bash script:

SSH_AUTH_SOCK=$(find /tmp -name 'agent.*' -user username);
export SSH_AUTH_SOCK;

Make sure you substitute username with your username. See LinuxHints/CrontabFormat for more information on Cron.

SSH Security

Some useful links on SSH security:

LinuxHints/SSHwithoutPasswords (last edited 2008-07-28 12:12:02 by 86)