Using ssh-agent with ssh
Back in 2002, 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 from your machine (local) to a remote machine (remote) without typing in a password.
Executive Summary
- Create a key pair on the local machine.
- Put the public key on any remote machines.
- Run ssh-agent to cache login credentials for the session. ssh-agent requires the user to "unlock" the private key first.
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 — your local computer. Do not do this over the internet. 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.
you@local$ 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 you@local$
- To use the key on other hosts you will be connecting from, copy the
~/.ssh/id_dsakey to the other hosts:However, it is probably better just to generate new keys for those hosts.you@local$ scp ~/.ssh/id_dsa you@another-box:.ssh/
- Make sure the public key is in the
~/.ssh/authorized_keysfile on the hosts you wish to connect to. You can use a password authenticated connection to do this:Note: If an older version of ssh is running on the remote host, you may have to use theyou@local$ cat ~/.ssh/id_dsa.pub | ssh you@remote 'cat - >> ~/.ssh/authorized_keys' you@remote's password: you@local$
~/.ssh/authorized_keys2file. Note: If your local machine is Windows, tryAlso note: If theC:\> type %HOME%/.ssh/id_dsa.pub | ssh you@other-host "cat - >> ~/.ssh/authorized_keys" you@other-host's password: C:\>
remoteserver is Windows, you will probably want to usetypeinstead ofcatfor 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
you@local$ ssh you@remote Enter passphrase for DSA key 'you@example.com': ^D you@local$
sshd_configon the server has been configured to do DSA authentication. Look forDSAAuthentication yesor get your system administrator to add it if necessary.)
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_SOCKenvironment 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.xsessionfile (You can substitute your window manager for gnome-session if that is what you use):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. The above solution is the best one if you are logging in via GDM or another graphical login manager under *nix. However, if you login at the console, or want to use ssh-agent under Cygwin, you'll have to use one of the following solutions. If you want to, say, put it in yourssh-agent gnome-session.profile, then you might try the following setup. Kyle Amon has provided the following bit for a.bash_profile:This brings# # setup ssh-agent # # set environment variables if user's agent already exists [ -z "$SSH_AUTH_SOCK" ] && SSH_AUTH_SOCK=$(ls -l /tmp/ssh-*/agent.* 2> /dev/null | grep $(whoami) | awk '{print $9}') [ -z "$SSH_AGENT_PID" -a -z `echo $SSH_AUTH_SOCK | cut -d. -f2` ] && SSH_AGENT_PID=$((`echo $SSH_AUTH_SOCK | cut -d. -f2` + 1)) [ -n "$SSH_AUTH_SOCK" ] && export SSH_AUTH_SOCK [ -n "$SSH_AGENT_PID" ] && export SSH_AGENT_PID # start agent if necessary if [ -z $SSH_AGENT_PID ] && [ -z $SSH_TTY ]; then # if no agent & not in ssh eval `ssh-agent -s` > /dev/null fi # setup addition of keys when needed if [ -z "$SSH_TTY" ] ; then # if not using ssh ssh-add -l > /dev/null # check for keys if [ $? -ne 0 ] ; then alias ssh='ssh-add -l > /dev/null || ssh-add && unalias ssh ; ssh' if [ -f "/usr/lib/ssh/x11-ssh-askpass" ] ; then SSH_ASKPASS="/usr/lib/ssh/x11-ssh-askpass" ; export SSH_ASKPASS fi fi fi
SSH_AUTH_SOCKandSSH_AGENT_PIDas environment variables into the current shell. Thetrapshould 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:Finally, this solution from Joseph M. Reagle by way of Daniel Starin:ssh-add -D ssh-agent -k
This last version is especially nice since it will see if you've already started ssh-agent and, if it can't find it, will start it up and store the settings so that they'll be usable the next time you start up a shell. (Update 25 Sep 2007: Adam Piper pointed out that quoting anything that usesSSH_ENV="$HOME/.ssh/environment" function start_agent { echo "Initialising new SSH agent..." /usr/bin/ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}" echo succeeded chmod 600 "${SSH_ENV}" . "${SSH_ENV}" > /dev/null /usr/bin/ssh-add; } # Source SSH settings, if applicable if [ -f "${SSH_ENV}" ]; then . "${SSH_ENV}" > /dev/null #ps ${SSH_AGENT_PID} doesn't work under cywgin ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || { start_agent; } else start_agent; fi
$HOMEis necessary on Cygwin.) - Finally, time to type a password. The last one of this session, maybe.
you@local$ ssh-add ~/.ssh/id_dsa Need passphrase for ~/.ssh/id_dsa (you@example.com). Enter passphrase: you@local$
- Now, you should test it:Jubilation! It worked! Go forth and conquer! (If it doesn't work, try
you@local$ ssh you@remote Last login: Tue Apr 25 13:40:21 1492 from europe.com Sun Microsystems Inc. SunOS 5.7 Generic October 1998 No mail. [you@remote]$
chmod -R go-rw ~/.sshon 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.
If you want to understand a little bit more about how all this works, read An Illustrated Guide to SSH Agent Forwarding.