SSH Keys
I have for the longest time been using public key authentication on almost every shell I use. One of the things that most people do with these keys is set them up without passwords to allow them to open connections to shells without typing passwords. Whilst this increases the ease of use it obviously misses the point. That sort of short-cut is taken without considering how you can use passwords but still have the ease of use.
Lets see how SSH works without any setup:
$ ssh znx@work.host.com znx@work.host.com's password: (password)
Type in your password and you get a shell. Now lets generate some keys and login with those.
$ cd ~/.ssh $ ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/home/mark/.ssh/id_rsa): id_workhost Enter passphrase (empty for no passphrase): (passphrase) Enter same passphrase again: (passphrase) Your identification has been saved in id_workhost. Your public key has been saved in id_workhost.pub. The key fingerprint is: 75:9c:c0:a3:52:7e:92:3c:f7:9d:c0:ff:0b:18:8c:48 znx@home.local The key's randomart image is: +--[ RSA 2048]----+ | .. | | . oo . | | E o.o+ | | o O.=.o | | oS* + + . | | + + | | . . . | | . .| | ..| +-----------------+
So the private key is called id_workhost and the public key is called id_workhost.pub. The private key should be kept safe at all times; the public key however is what we need to put out onto the other machine. If you have ssh-copy-id you can use that instead of the follow. So lets do that now:
$ scp ~/.ssh/id_workhost.pub znx@work.host.com: znx@work.host.com's password: (password) id_workhost.pub 100% 1766 1.7KB/s 00:00 $ ssh znx@work.host.com znx@work.host.com's password: (password) work$ cat id_workhost.pub >> ~/.ssh/authorized_keys work$ rm id_workhost.pub work$ logout $ ssh -i ~/.ssh/id_workhost znx@work.host.com Enter passphrase for key '/home/znx/.ssh/id_workhost': (passphrase) Last login: Wed Apr 6 08:25:16 2011 from home.local work$
So we are now using keys to login rather than passwords but it still requires a passphrase to be type in. The next step is to look at ssh-agent. This tool will hold keys in memory and allow thus allowing you to login without needing to unlock the key. So lets run it and see what it does:
$ ssh-agent SSH_AUTH_SOCK=/tmp/ssh-SdjNGn3604/agent.3604; export SSH_AUTH_SOCK; SSH_AGENT_PID=3605; export SSH_AGENT_PID; echo Agent pid 3605;
Not exactly useful until you spot that it is actually setting up bash variables. So the way we want to run ssh-agent is as follows:
$ eval `ssh-agent` Agent pid 3609 $ echo $SSH_AGENT_PID 3609
That’s more like it, so once you have a running agent you can now start to add keys into its memory.
$ ssh-add ~/.ssh/id_workhost Enter passphrase for /home/mark/.ssh/id_workhost: (passphrase) Identity added: /home/mark/.ssh/id_workhost (/home/mark/.ssh/id_workhost)
With the key added we can now login to the host with the unlocked key:
$ ssh znx@work.host.com Last login: Wed Apr 6 22:14:49 2011 from home.local work$
Now that is a login without a password or a passphrase because the key is unlocked and held by ssh-agent. Whilst ssh-agent is useful if you retain one shell open all the time, the moment you close that shell you lose the variables of the running ssh-agent which means that you will not be able to use it. This also means that if you are running scripts (say via cron) that you can no longer automate the logins. So back to keys without passphrase? NO!
There is a very nice tool that can help us out and it is called keychain. Simply add this to your ~/.bash_profile:
keychain --quiet ~/.ssh/id_workhost source ~/.keychain/*-sh
You should also add this to your ~/.bashrc:
source ~/.keychain/*-sh
Now login to your shell again and you should see that you are prompted to put in passwords. This is keychain loading your keys in. It looks something like this:
Identity added: /home/mark/.ssh/id_mine (/home/mark/.ssh/id_mine)
You will see that you can now login without passphrase to your host again. Indeed all the shells you open will now grab the keychain information and login immediately.
This means that you will only get prompted for passphrases once when you login and then you will have the ability to login to your shells without passphrases. Obviously you should add keys for your regular hosts. You can add keys on the fly with keychain at the command line:
$ keychain ~/.ssh/id_someotherkey
And it will be stored until your ssh-agent is closed. If you wish to clear the keys you have added then simply do:
$ keychain --clear
What all this means is that you can now run scripts with passphrase protected keys because all you need to do is source the running ssh-agent within your script:
#!/bin/sh # Some remote copy script source ~/.keychain/*-sh scp znx@work.host.com:nightly-copy.file local/nightly-copy.file
As long as the key is load the script will work.
Doing this ensures that even if the private key falls into the wrong hands that it is still secured with a passphrase and you haven’t just opened up your remote hosts to attack.
There is solutions for this under Windows as well; the PuTTY installer will provide you with a tool called Pageant. This works in an identical way to ssh-agent; loading keys into its memory to allow PuTTY to login with unlocked keys.
Check out some of the other SSH tips I’ve published which will ease the logins even further!