I went searching for a good, general page that would explain how to do passwordless logins using ssh-agent and didn't find much at the time (now there is much more out there). So I wrote this page.
Goals
Get a secure, encrypted connection to a remote machine without typing in a password.
Methods
Use OpenSSH to handle the authentication.
For Windows users, the methods I describe here will work with the OpenSSH that is part of the CygWin toolset.
Anyway, here is how to set up a pair of keys for passwordless authentication via ssh-agent.
- Generate the keys. Do this on the host that you want to connect
from.
Note: Older versions of OpenSSH (1.2.xx) and, perhaps, commercial SSH may require that you have to use RSA keys. In this case substitute "RSA" for "DSA" after "-t" and "identity" for "id_dsa". Continue to substitute "RSA" where you see "DSA" throughout. Everything else should be the same.
Also Note: On Windows machines, the command prompt doesn't understand the ~ which on Unix machines means "the home directory". Instead use %HOME% wherever you see the tilde.
$ ssh-keygen -t dsa -f ~/.ssh/id_dsa -C "you@example.com" Generating DSA keys: Key generation complete. Enter passphrase (empty for no passphrase): USE-A-PASSPHRASE Enter same passphrase again: USE-A-PASSPHRASE Your identification has been saved in ~/.ssh/id_dsa Your public key is: 1024 35 [really long string] you@example.com Your public key has been saved in ~/.ssh/id_dsa.pub $
- To use the key on other hosts you will be connecting
from, copy the ~/.ssh/id_dsa key to the other
hosts:
$ scp ~/.ssh/id_dsa you@another-box:.ssh/
- Make sure the public key is in the ~/.ssh/authorized_keys
file on the hosts you wish to connect to. You can use a
password authenticated connection to do this:
$ cat ~/.ssh/id_dsa.pub | ssh you@other-host 'cat - >> ~/.ssh/authorized_keys' you@other-host's password: $
Note: If an older version of ssh is running on the remote host, you may have to use the ~/.ssh/authorized_keys2 file.
Note: If your local machine is Windows, try
C:\> type %HOME%/.ssh/id_dsa.pub | ssh you@other-host "cat - >> ~/.ssh/authorized_keys" you@other-host's password: C:\>
Also note: If the remote server is Windows, you will probably want to use type instead of cat for the second half of your command.
- Verify that DSA authentication works:
If you don't get the prompt for your DSA key, then something has gone wrong. (One thing to check: verify that sshd_config on the server has been configured to do DSA authentication. Look for DSAAuthentication yes or get your system administrator to add it if necessary.)$ ssh you@example.com Enter passphrase for DSA key 'you@example.com': ^D $
Now that that works, you will want the passwordless part, right?
- Start up ssh-agent. You can have it create a
subprocess which inherits the SSH_AUTH_SOCK
environment variable, or you can run it as a daemon.
Since I run gdm on Debian, ssh-agent is started automatically when I log in. If you don't have this benefit, you can get it by putting the following line at the end of your .xsession file (You can substitute your window manager for gnome-session if that is what you use):
ssh-agent gnome-session
Which basically means that ssh-agent starts up, creates a socket, sets up a couple of environment variables and then starts up gnome-session. That way all of the programs run in Gnome have access to the agent.
If you want to, say, put it in your .profile, then you might try the following setup. In my .bash_profile, I have
SSHAGENT=/usr/bin/ssh-agent SSHAGENTARGS="-s" if [ -z "$SSH_AUTH_SOCK" -a -x "$SSHAGENT" ]; then eval `$SSHAGENT $SSHAGENTARGS` trap "kill $SSH_AGENT_PID" 0 fi
(If you use csh or tcsh, see this note for the equivilent piece of code for your .login shell.)
This brings SSH_AUTH_SOCK and SSH_AGENT_PID as environment variables into the current shell.
The trap should kill off any remaining ssh-agent process. If it doesn't, you won't want the ssh-agent daemons sitting around, so you might want the following in your .logout:
kill $SSH_AGENT_PID
An alternative, provided by John Buttery, is
if [ ${SSH_AGENT_PID+1} == 1 ]; then ssh-add -D ssh-agent -k > /dev/null 2>&1 unset SSH_AGENT_PID unset SSH_AUTH_SOCK fi
- Finally, time to type a password. The last one of this session,
maybe.
$ ssh-add ~/.ssh/id_dsa Need passphrase for /home/mah/.ssh/id_dsa (you@example.com). Enter passphrase: $
- Now, you should test it:
$ ssh you@example.com Last login: Tue Apr 25 13:40:21 1492 from europe.com Sun Microsystems Inc. SunOS 5.7 Generic October 1998 No mail. [you@example.com]$
Jubilation! It worked! Go forth and conquer! (If it doesn't work, try chmod -R go-rw ~/.ssh on the server and try again.)
Ok, so, did it work or no? Let me know.
If you want to use this setup for editing remote files in emacs under Windows, check out my Tramp-on-NT page.
Acknowlegements
8 Jan 2003: Stefan Adams pointed out that ~/.ssh and ~/.ssh/authorized_keys cannot be group or world writable.
27 Aug 2002: David Previti offered the working Windows-client to Windows-server key copy command as well as other Window-isms.
9 Aug 2002: Lloyd Smith suggested verifying that sshd_config is set up to do DSA authentication if it fails initially.
3 Jul 2002: Ismaeel Abdur-Rasheed provides these *csh equivilents for those using csh or its derivatives. To the .login script, add the following:
set sshAgent=/usr/bin/ssh-agent set sshAgentArgs="-c" set tmpFile=exportAgentEnv if ( -x "$sshAgent" ) then if ( ! $?SSH_AUTH_SOCK ) then $sshAgent $sshAgentArgs | head -2 > $tmpFile source $tmpFile rm $tmpFile echo "ssh agent started [${SSH_AGENT_PID}]" ssh-add endif endif
And, to the .logout:
if ( $?SSH_AGENT_PID ) then echo "killing ssh agent [${SSH_AGENT_PID}]" ssh-add -D kill $SSH_AGENT_PID unset SSH_AGENT_PID unset SSH_AUTH_SOCK endif
3 Jul 2002: David Newcomb offered the trick of putting trap 0 in the login/profile script.
18 May 2002: A more complete logout script from John Buttery. Also added tips on using RSA rather than DSA keys.