ALINK="#FF0000">

LINUX GAZETTE


[ Prev ][ Table of Contents ][ Front Page ][ Talkback ][ FAQ ][ Next ]

"Linux Gazette...making Linux just a little more fun!"


Using ssh-agent for SSH1 and OpenSSH

By Jose Nazario


Recently I was discussing with a friend how to use SSH to achieve secure, passwordless authentication. He was looking for a way to automate some file transfers and wanted to do it using an expect script (to pump in his passphrase when prompted) to automate the process. I suggested 'ssh-agent', but didn't know quite how to make it work at the time. Since then, I've learned, and it's quite easy.

Using the agent for key based authentication is a method to facilitate communications. You can use key based authentication without the agent, you just have to unlock the key every time you want to use it. Note that by default the ssh client will attempt to authenticate using keys before a password. The agent just makes management of this much easier.

There are several implementations of the ssh protocol, each with its own peculiarities of usage and behavior. The two most common implementations are from openssh.org) and ssh.com). OpenSSH was created for OpenBSD and is thus free software. ssh.com's ssh is a commercial product that is no-cost for open-source operating systems (and for trial, non-commercial and educational use on other OSes). Each implementation of ssh has some slight peculiarities of usage and behavior.

As if multiple implementations weren't enough, there are also two ssh protocols, SSH1 and SSH2. This article focuses on using the SSH1 protocol, which differs slightly from the SSH2 protocol. Previous articles in Linux Gazette have introduced the use of ssh-agent for ssh2 (see below). Note that, by default, ssh2 uses DSA keys, and different directory and file names from ssh1, though compatability can be introduced. Since most people use the SSH1 protocol (data from recent University of Alberta Internet scans using 'scan-ssh'), we will focus on this version. OpenSSH follows, almost perfectly, the syntax of the ssh.com ssh1 program for agent based key management. Note that it differs for ssh2 handling (not covered here).

The benefits of RSA based authentication are numerous, frankly:

Mutual authentication
In RSA authentication, each side has to verify that they are who they claim to be. The client verifies the server is who they should be (based on their public key, stored in ~/.ssh/known_hosts), and the server verifies the authenticity of the identification of the client via an RSA key. This is used to protect against man-in-the-middle attacks based on the veracity of the server keys.

Stronger passphrase protection
RSA keys can be protected by a passphrase, not a password, which translates into a larger space to search via brute force methods. So, instead of "p@55w0rd" you can use "Toby Betts is David Monk's roommate and is dating F0xT4il." (You should use something significantly more complex than either of those examples.)

Stronger authentication
The strength of the authentication means, in this case an RSA keypair, is quite strong. RSA encryption is known to be expensive and infeasible to a brute force attack. Can't say this for passwords.

Easier on the user
Dislike having to type passwords often? Me too. After a few moments of setup (which is about the same number of keystrokes as a password authentication session), its now effortless, just connect to the remote host and your authentication is taken care of.

Hence, I can't think of any reason (other than not knowing how, which this document is trying to teach you) why you shouldn't use it.

Components

First up, our cast of characters. These are the components that play in this whole thing, so get to know them:

ssh
The client ssh program. In this case we're going to work only with ssh.com's ssh1 program (ie ssh-1.2.30) and OpenSSH (ie openssh-2.5.2).

sshd
The server program, again a version 1 server or an OpenSSH server.

ssh-agent
The agent program which handles the interaction of your public keys and the ssh client program.

ssh-add
A tool used to load (or unload) RSA private keys into the cache for ssh-agent. They communicate by using a small socket on the client machine.

ssh-keygen
A tool used to generate the public and private keypairs used in RSA based authentication.

~/.ssh/identity
The file containing your private key. Keep this one well guarded!
-rw-------   1 jose     users         530 Feb  8 12:14 identity

~/.ssh/identity.pub
The file containing the public component of your RSA key pair.
-rw-------   1 jose     users         334 Feb  8 12:14 identity.pub

~/.ssh/authorized_keys
The file containing a list of public keys which match your private keys. This is what's used to match up for your authentication.

Basic Steps in Agent Based Authentication

OK, let's begin. Our order of operations is quite simple: generate a keypair, distribute the public keys to the hosts to which we're going to connect, and then set up our agent.

Before we begin, let's make sure the target server allows RSA key based authentication:

$ grep RSA /etc/sshd_config
RSAAuthentication yes

If that says 'no', then this whole thing is moot. Speak to your administrator if you need to.

We use ssh-keygen to generate the keypair. A typical session looks like this:

$ ssh-keygen
Initializing random number generator...
Generating p: ............................++ (distance 446)
Generating q: ...............++ (distance 168)
Computing the keys...
Testing the keys...
Key generation complete.
Enter file in which to save the key (/home/jose/.ssh/identity):
Enter passphrase:
(not echoed)
Enter the same passphrase again:
(not echoed)
Your identification has been saved in /home/jose/.ssh/identity.
Your public key is:
1024 37 13817424072879097025507991426858228764125028777547883762896424325959758548762313498731030035107110571218764165938469063762187621357098158111964592318604535627188332685173064165286534140697800110207412449607393488437570247411920664869426605834174366309317794215856900173541953917001003859838421924037121230161484169444067380979 jose@biocserver
Your public key has been saved in /home/jose/.ssh/identity.pub

So, now we have the two pieces we need, our public and private keys. Now, we have to distribute the public key. This is just like PGP, frankly, you can share this with anyone, then you can login without any hassle. I'll use 'scp' to copy it over:

$ scp .ssh/identity.pub jon2@li:~/.ssh/biocserver.pub
jon2@li's password:
(not echoed)
identity.pub | 0 KB | 0.3 kB/s | ETA: 00:00:00 | 100%

Having copied it there, I will now login to the target machine (in this case the SCL machine 'li') and add it to the list of keys that are acceptable:

li$ cat biocserver.pub >> authorized_keys

OK, now li is all set to let me authenticate using my RSA private key I generated above. Let's go back to my client machine and set up ssh-agent. First, before I invoke the agent, let's look at a couple of environmental variables in my shell:

$ env | grep -i SSH
SSH_TTY=/dev/ttyp3
SSH_CLIENT=129.22.241.148 785 22

Now let's invoke ssh-agent properly. It starts a subshell, so you have to tell it what shell to invoke so it can set it up right.

$ ssh-agent /bin/bash

And it's now set up my environment correctly:

$ env | grep -i SSH
SSH_TTY=/dev/ttyp3
SSH_AGENT_PID=3012
SSH_AUTH_SOCK=/tmp/ssh-jose/ssh-3011-agent
SSH_CLIENT=129.22.241.148 785 22

The two new variables, SSH_AGENT_PID and SSH_AUTH_SOCK, will allow the agent and accessory applications (ie the ssh client, the cache loading tool ssh-add, and such). The sockets are just regular files in the /tmp directory:

$ ls -l /tmp/ssh-jose/

total 0
srwx------   1 jose     users           0 Apr 24 13:36 ssh-3012-agent

So, now that the agent is properly set up, load the cache with your private key. Remember, the agent communicates with the client to hand off your private key when you want to authenticate. Invoking it without any arguments assumes the standard, default private keyfile:

$ ssh-add1
Need passphrase for /home/jose/.ssh/identity (jose@biocserver).
Enter passphrase:
(not echoed)
Identity added: /home/jose/.ssh/identity (jose@biocserver)

The passphrase you use here is to ensure "yes, it's me, I have a right to use this key", and it's the same passphrase you set up above when you ran ssh-keygen. Now that the key is loaded, let's look at the cache, using the -l (for 'list') option to ssh-add:

$ ssh-add -l
1024 37 11375588656963284515711893546976216491501314848762129298719958615531627297098741828662897623987120978747144865157469714395736112700558601876305400606604871996923286317135102021232606807975642627653113389875325214757393348628533138103638880715659452391252482099813547642625002508937138181011315411800330612532401318392577 jose@biocserver

Now, when you ssh to another host, you will not get prompted for a passphrase, the private key would have been used as your authenticator using ssh-agent!

$ ssh -l jon2 li
Last login: Tue Apr 24 14:53:39 2001 from biocserver.bioc.
You have mail.
bash-2.03$

Look, Mom, no passphrase needed!

Note that you can alter the above, if you would like, to add some flexibility. First, you can use the output of the ssh-agent program (when invoked without a shell argument), to modify the current shell and set up the agent socket for communication:

$ eval `ssh-agent`
Agent pid 19353;

Now you can add keys as described above, and you have not started a subshell, only having modified the login shell you are currently using. The eval and backticks combination is needed to handle the output that the agent presents to modify the shell. This is because child processes cannot modify the parent shell's parameters.

A second modification you can do is to start your X desktop, such as GNOME or KDE, as the argument to ssh-agent. This will cause every X client locally started to be aware of how to communicate with the agent, allowing for greater ease when you use terminals to log in to other hosts.

One important note

Before we end this, let's say one very important things: the cache is loaded and you have authenticated yourself to use your private keys. This keeps them in memory. So, what if you walk away from your workstation? Anyone would have access to your hosts that let you authenticate using RSA keys.

That said, you can unload specific keys using ssh-add's '-d' flag, or you can unload all of them using the '-D' flag:

$ ssh-add -D
All identities removed.

This is a good thing to do when you walk away from your workstation. It'd be neat to have a small idle timeout feature, or link this into the screensaver command on your system, or an APM suspend on your laptop.

Doing it the wrong way

Invoking ssh-agent without any arguments, which is to say improperly, starts a subshell, but it hasn't set the correct parameters in your shell. It will echo what it would have set, but they are not set:

$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-jose/ssh-3019-agent; export SSH_AUTH_SOCK;
SSH_AGENT_PID=3020; export SSH_AGENT_PID;
echo Agent pid 3020;

Let's have a look and see if the correct environmental variables have been set in our shell. These are needed for the agent to work properly, as we saw above:

$ env | grep -i ssh
SSH_TTY=/dev/ttyp3
SSH_CLIENT=129.22.241.148 785 22

The consequences of this are evident when you try and add keys to the cache:

$ ssh-add
Need passphrase for /home/jose/.ssh/identity (jose@biocserver).
Enter passphrase:
(not echoed)
Could not open a connection to your authentication agent.

It can't find the socket or the process ID, which is stored in this variable. As such, no keys are available in the cache.

Conclusion

This has been the most rudimentary of introductions on how to use ssh-agent for strong authentication. You should experiment if you'd like to learn more, such as adding non-default keys, and read the excellent documentation in the OpenSSH distribution. The O'Reilly snail book, entitles "SSH: Secure Shell, The Definitive Guide", is truly a great reference for SSH, and is strongly recomended.

Previous LG articles on the ssh suite

Jose Nazario

José is a Ph.D. student in the department of biochemistry at Case Western Reserve University in Cleveland, OH. He has been using UNIX for nearly ten years, and Linux since kernels 1.2.


Copyright © 2001, Jose Nazario.
Copying license http://www.linuxgazette.net/copying.html
Published in Issue 67 of Linux Gazette, June 2001

[ Prev ][ Table of Contents ][ Front Page ][ Talkback ][ FAQ ][ Next ]