Getting screen and ssh-agent to cooperate with each other
Certificate based authentication is probably one of the most convenient features of ssh. Most of the systems I log into via ssh on a regular basis are configured with public key authentication. Also, I am very fond of screen. Unfortunately, due to the way ssh-agent works, it does not cooperate very well with screen. The program ssh-agent serves two purposes. First, it caches passwords for ssh private keys. Second, it allows for ssh authentication forwarding alongside a regular ssh login so ssh connections originating from the remote session can be transparently and securely authenticated with the certificate residing on the user's computer. The environment variable
SSH_AUTH_SOCK informs any ssh command run in the session where to find the socket to communicate with ssh-agent.
Since ssh-agent lives and dies with the login session, the moment one disconnects from screen and logs out the ability to use ssh authentication forwarding is disrupted until the screen session is completely restarted. This essentially renders screen useless. The problem is that the name of the socket unique to every instance of ssh-agent and the new information does not get propagated down to any sessions running in screen.
After a bit of googling, a couple of possible solutions presented themselves. Several involve external scripts and aliases to save and restore the environment variables associated with ssh-agent. This solutions seemed a bit too cumbersome. The solution that I finally decided on is very simple and involves adding two lines to two config files in the home directory.
This line goes in your profile script (
test $SSH_AUTH_SOCK && ln -sf "$SSH_AUTH_SOCK" "/tmp/ssh-agent-$USER-screen"
And this line goes in
setenv SSH_AUTH_SOCK "/tmp/ssh-agent-$USER-screen"
All this does is create a symlink in
/tmp that points to the ssh-agent socket. The symlink has a constant name so that it can be used in screen without any additional trouble. The first line creates and updates the symlink on every login so that it always points to an active socket. The second line overrides the environment variable in the screen session so that the new link is accessible to all of the screen session's terminals.
I have been using this simple solution for quite some time now with no issues.