Doing It All with OpenSSH, Part 2

Keys, keys and more keys.

Welcome back to the Sysadmin's Corner and the continuing saga of secure communications, SSH-style. Logging in to an SSH server is easy enough and provides you with secure communications, while still opening you up to the whole world. You could set up a firewall that allows in certain IP addresses only to port 22, but that presents another problem. If you are on the road and you need access to your own system, you might be connecting from an untrusted system with a dynamic IP. A nice iptables rule isn't going to help here, unless you've got somebody permanently standing by who can answer your phone call and enter the commands for you--somebody with root access, no less. No matter how you look at it, it can get messy.

Another option is to leave port 22 wide open and set your server to allow only public key authentication. This option requires a little more work than merely running sshd and forgetting about it. But as an added bonus, you can securely log in without a password. Did he just say "without a password"? Yes, he did, and you can do so securely. In fact, public key authentication can be safer than the classic password system because knowing the password isn't enough.

Here's how it works. Using a key generation program, you create a key pair consisting of a public key, which is copied to the server, and a private key, which you keep on your PC and guard with your life. No authentication can take place without both keys.

To generate your own public key, use the ssh-keygen command, specifying the encryption type. In the following example, I used RSA encryption, the one most people should use. Other encryption types include rsa and dsa. There's also an rsa1 for the old protocol 1 ssh, but odds are that you won't need this--at least not for now.

If you type ssh-keygen -t rsa, the output of the command looks like this:

                 Generating public/private rsa key pair.
                 Enter file in which to save the key (/home/mgagne/.ssh/id_rsa):
                 Enter passphrase (empty for no passphrase):
                 Enter same passphrase again:
                 Your identification has been saved in /home/mgagne/.ssh/id_rsa.
                 Your public key has been saved in /home/mgagne/.ssh/
                 The key fingerprint is:
                 0b:76:f2:a3:54:20:86:74:fe:9d:64:56:c4:85:a9:7f mgagne@ultraman

You can pretty much accept the question regarding the location for storing the key. Pay attention, however, to the second question, the demand for a passphrase. If you wanted to, you could enter nothing here, upload your key to the server and have no passwords whatsoever when you connect. After all, it sounds like you simply are exchanging one password for another. There is a catch, however, with this idea. If someone was to get a copy of your private key, that person would have no trouble getting into all your other systems. Given that danger, you definitely want to protect yourself with a passphrase--so what have you gained?

Well, as it turns out, there is a way around this roadblock, and I'll tell you about it shortly. But first, I would like to tell you what you do with your public key. The ssh-keygen command creates a file named for your public key, and you need to get its contents to the remote system. That key is a text file, and its contents look something like what is shown below. Although the contents below span a few lines, in reality, this is one unbroken line of text.

                 WhWaPd+YE1fmqzU2nBRxQ1Ud2xqjFCcwdSWesE= mgagne@ultraman

Your next step it to connect to the remote server where the sshd process is running. You might want to open another window to do this, because we'll be doing a little copying and pasting. That should put you in the user's home directory. From there, cd to the .ssh directory in the home directory and look for a file called authorized_keys. If it isn't there, create it. Now, copy and paste the key into the authorized_keys file, keeping in mind the key must be copied exactly. You also could transfer it to the remote system and append it to the authorized_keys file, like this:

                 cat >> $HOME/.ssh/authorized_keys

A word of caution before we continue: the permissions on this file cannot be group or world writable or this procedure will not work. You have to do a chmod 644 authorized_keys to make sure the file can be written only by the owner.

When you next connect to the remote system with ssh -l user_name remote_sys, you'll connect without being asked for a password. As I mentioned, however, creating your public/private key pair without a password probably is a bad idea. If someone gets his or her hands on your keys, all is lost; any security you might have gained by running with the secure shell is pretty much gone. Your only option is to use a passphrase when you generate your key-pair with ssh-keygen, but then you are back to using a password--the thing I promised you freedom from at the beginning of the article. Is there no way out?

This conundrum is exactly where a fine little program called ssh-agent comes to the rescue. If you already have created your passphrase-free key-pair, start again and provide a passphrase this time. Move the public key over to your server (remember to get rid of the old pubkey from the .ssh/auhorized_keys file), and test your connection. You should be asked for your passphrase, but not the user's password. So far, so good?

Before you start ssh-agent, you may want to look for its process because your window manager may start it for you. For instance, on my Mandrake 9.1 system, this little bit of code exists in the system wide /etc/X11/Xsession file.

                  AGENT=$(type -p ssh-agent)
                  if [ -x "$AGENT" -a -z "$SSH_AUTH_SOCK" ]; then
                      if [ -r $HOME/.ssh/identity -o -r $HOME/.ssh2/identificati
                           SSH_AGENT="$AGENT --"

In fact, if I do a ps ax | grep ssh-agent on my notebook, I see the following:

                3209 ?        S      0:00 ssh-agent
                3475 ?        S      0:00 /usr//bin/ssh-agent -- /bin/sh -c #!/b

So, ssh-agent clearly is running, and yet I still am asked for a passphrase when I connect to my remote system. Obviously, simply having ssh-agent running isn't enough. That's because while ssh-agent might be running, it doesn't know your passphrase yet. You enlighten the process with the ssh-add command.

                 $ ssh-add
                 Enter passphrase for /home/mgagne/.ssh/id_rsa:
                 Identity added: /home/mgagne/.ssh/id_rsa (/home/mgagne/.ssh/id_

As you can see, I'm asked for a passphrase for my private key. After I've entered it, I then am able to connect to the remote system without a passphrase--simple and secure. Luckily, ssh-agent doesn't remember the information after you logout. Otherwise, once a passphrase was entered with ssh-add, the security of a protected passphrase would be pointless if somebody broke into your system.

You can use ssh-agent even if you aren't running an X window graphical environment, by the way. Let's pretend you are logged in to a text-only session. From the command line, you could type ssh-agent /bin/bash, at which point you then would have a bash shell wrapped by ssh-agent. From there, you can execute the ssh-add command, enter your passphrase and work with your various systems accordingly.

We've come full circle now. Everything works as it should, and you are ready to switch your sshd server over to an authentication that doesn't allow passwords at all. That way you can leave the port 22 connection open to the world, knowing that only fully authenticated public key clients can connect to your system. Here's what you do. Open the /etc/ssh/sshd_config file and look for the following line:

                 # PasswordAuthentication yes

The line is likely to be commented out because allowing password authentication is the the default. Uncomment the line, and change the yes to no. Then, restart your sshd server daemon. If you are feeling a bit worried about locking yourself out, you could leave the current process running and start a second server on another port, such as 2222, as I covered in my previous column.

                 /usr/sbin/sshd -p 2222

Now, if you try to log in to the server on port 2222 without the appropriate public key on the server, you won't get any further.

                 $ ssh -p 2222 -l marcel remotesys
                 Permission denied (publickey,keyboard-interactive).

Well, I think I've definitely used up my quota of words for today. Next time around, I'll tell you how to do this with your (gasp!) Windows PCs. I also will talk about remote program execution, secure transfers and many other exciting things. Until next time, I hope you are feeling a little bit more secure.

Marcel Gagné is Linux Journal's Chef Français and a Linux true believer. His new book Moving to Linux: Kiss the Blue Screen of Death Goodbye! will be out in August 2003. You can find out more from his web site at



Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Anonymous's picture

ChallengeResponseAuthentication no

due to Maximilian Ataian

you also have to set ChallengeResponseAuthentication to no if you're using Pam

hopfully saving some of yours an hour searching ;)

Re: Doing It All with OpenSSH, Part 2

Anonymous's picture

Great article. I have actually been using public key *plus* password on my connection to homeserver - maybe I'm paranoid. I keep putty, by private key and a few other programs on a usb-key chain thingy so I can plug into a Windows box just about anywhere and get onto my home server.

I also use X11 tunnelling and have setup a tunnel for vnc. However I think you could use ssh tunnelling for just about anything that will accept proxy connections. Would like to hear more about using ssh and tunnelling to set up a whole VPN solution.
GJS, Western Australia

Re: Doing It All with OpenSSH, Part 2

Anonymous's picture

If you use that usb-key thingy in unknown machines, then probably you are not paranoid enough.

You could also be paranoid about your key being copied, and your passphrase being recorded from the keyboard :)

Re: Doing It All with OpenSSH, Part 2

Anonymous's picture


Please, can you tell me how to configure X11 tunnel?

sincerely yours


Re: Doing It All with OpenSSH, Part 2

Anonymous's picture

Very good article!! linux newbie here and this is so clearly written that I feel comfortable setting it up myself!!

Re: Doing It All with OpenSSH, Part 2

Anonymous's picture

Great article!

I'll try it out tomorrow, so that I can get some work done from my home machine ;-)

Keep up the good work!

Re: Doing It All with OpenSSH, Part 2

Anonymous's picture

Presumably if one is roaming the world and logging in ad hoc from various clients, one then would need the public key on any given client in order to perform logins without a password, if I'm not missing the point. Not to be a wet blanket, but doesn't toting around a copy of the public key on physical media and possibly forgetting to remove it from a client after accessing it from removeable media or copying it to the client represent a far larger risk to security than simply using a password and eschewing use of keys? A failed login to SSH results in a multisecond delay so I'd guess brute force guesswork would not be very helpful to an attacker.

I'm sincerely sure I'm missing something here, because the author is way more expert on this topic than I am.

Re: Doing It All with OpenSSH, Part 2

Anonymous's picture

From O'Reilly Secure linux cookbook:

"Public-key authentication lets you prove your identity to a remote host using a cryptographic key instead of a login password. SSH keys are more secure than passwords because keys are never transmitted over the network, whereas passwords are (albeit encrypted). Also, keys are stored encrypted, so if someone steals yours, it's useless without the passphrase for decrypting it. A stolen password, on the other hand, is immediately usable.

An SSH "key" is actually a matched pair of keys stored in two files. The private or secret key remains on the client machine, encrypted with a passphrase. The public key is copied to the remote (server) machine. When establishing a connection, the SSH client and server perform a complex negotiation based on the private and public key, and if they match (in a cryptographic sense), your identity is proven and the connection succeeds."

So, it seems you need the key AND a passphrase.

Re: Doing It All with OpenSSH, Part 2

Anonymous's picture

Generally, when you create a keypair with ssh-keygen, you are given the option of providing a passphrase to protect (encrypt) your private key. If you CR through the prompt, the key will be un-encrypted, but if you supply a password/passphrase to encrypt it, then it doesn't matter if the private key is left lying around. The only thing you will have to worry about is if someone has installed a keystroke logger on the machine you are using (therefore, you are better off using your own laptop at the client's site, since you can trust only what you have full control over).

Now, if you want to use your keypair to do remote command execution, then you have a problem, in that if the private key is encrypted, then you will have to provide the passphrase each time the ssh command is executed, which means that an encrypted private key is useless if you need to set up an unattended job using ssh. This, however, also has a solution. What you can do is load up the program "ssh-agent", which will load up a daemon that holds onto the un-encrypted version of your private key. The ssh-agent prints out some environment variables, one of which points to a socket, which ssh can use to talk to the agent. You load up your key in the agent using ssh-add, and then next time ssh needs access to your private key (i.e., it needs to answer a challenge from the server), it sends the challenge over to the agent to decrypt for it. (therefore, the private key never actually leaves the ssh-agent program).

So, if you want to use an encrypted private key to do remote command execution in an automated script (such as a cron job), the script would do the following:
First, start up an agent, and save the output to a file:
$ ssh-agent >/some/path/myagentvars
Now load the variables into your current environment:
$ . /some/path/myagentvars
And load your private key into the agent
$ ssh-add /some/path/my_private_key
Answer the prompt for your passphrase

Now, your cron job will look like this:

# check to see if a valid agent is running
if [ -f /some/path/myagentvars ]
. /some/path/myagentvars
if [ "$SSH_AGENT_PID" != "" ]
if kill -0 $SSH_AGENT_PID
# we have a valid agent
ssh user@remotehost command_to_execute
echo "No valid agent found"

Re: Doing It All with OpenSSH, Part 2

Anonymous's picture

all is nice and well - until you use the ssh-agent on an untrusted machine. all that's needed is something on the lines of:

ps -A | grep ssh-agent

then if it's there just have a peek at /dev/kmem and find the passphrase (albeit not the server that it's used with). then again, on an untrusted machine all bets are off.

on the other hand, if you do have a trusted machine then agent forwarding can be a nice trick too.

Re: Doing It All with OpenSSH, Part 2

Anonymous's picture

Isn't that already covered in the article? About 2/3 of the way down, it says:

"This conundrum is exactly where a fine little program called ssh-agent comes to the rescue. If you already have created your passphrase-free key-pair, start again and provide a passphrase this time. Move the public key over to your server (remember to get rid of the old pubkey from the .ssh/auhorized_keys file), and test your connection. You should be asked for your passphrase, but not the user's password. So far, so good? "

Then it goes on to explain how ssh-agent and ssh-add works.

Re: Doing It All with OpenSSH, Part 2

Anonymous's picture

Hopefully the author will explain the ssh-agent secure method of authentication (and authentication chaining), which requires a password on your keys. Ergo, even if they are distributed out - and - about the internet, there is still the necessity of acquiring the password for the key itself.

ssh-agent provides two things:
1. you type your password once for your key, and
2. agent challenge forwarding, so your authentication is transparently verified from one ssh box to another


X sessions

Anonymous's picture

I'm excited for your next article! My friend tells me he's running an X session through ssh. Nice!