9

A while back on StackOverflow, I asked this question about ssh-agent and crontab. I have a similar question now about ssh-agent and screen on linux systems.

So, on my Mac, ssh-agent launches at system startup, so it's always available to me. I think it would be true under my linux (redhat el5/fedora) if I were using X-Windows. However, this is a remote server machine and I'm always logging in via ssh.

I would love to have ssh-keys set up properly so I didn't have to enter my password multiple times during an svn update or commit. I'm happy to type in my passphrase once per session, and I discourage our team from having password-less ssh-keys.

For a brief shining moment, it seemed like doing "eval `ssh-agent -s`" in my .bash_profile, paired with a command to kill the ssh-agent when I logged out, would work. However, we make heavy use of screen in order to manage long-running interactive programs and development environments. If you start & stop ssh-agent as I just described, then it gets killed when you exit out of the terminal, and the screen's sub-sessions which used to be referring to that ssh-agent instance are abandoned.

So ... how can I be a console user, who uses screen, who uses a password with his ssh-keys, who doesn't have to type in the passphrase constantly?

6 Answers 6

5

With the following setup, you won't need any wrapper for invoking screen. Moreover, it avoids using /tmp (with the consequent security risks).

  1. Ensure you have an ~/tmp directory:

    mkdir ~/tmp
    
  2. Add to .screenrc the following line:

    setenv SSH_AUTH_SOCK "$HOME/tmp/ssh-agent-screen"
    
    • This ensures that inside screen, ssh looks for the socket always in the same location, rather than a changing path.
    • You must use setenv whichever shell you use, since it's a screen and not a shell command.
  3. Add to .bash_profile the following line:

    [ -n "$SSH_AUTH_SOCK" ] && [ "$SSH_AUTH_SOCK"!="$HOME/tmp/ssh-agent-screen" ] && ln -sf "$SSH_AUTH_SOCK" "$HOME/tmp/ssh-agent-screen"
    
    • This will link from the fixed location (where ssh looks) to the real one, and must appear after starting ssh-agent.
    • Using [ -n "$SSH_AUTH_SOCK" ] will properly prevent errors when SSH_AUTH_SOCK is not set.
    • [ "$SSH_AUTH_SOCK"!="$HOME/tmp/ssh-agent-screen" ] will prevent screen sessions linking $HOME/tmp/ssh-agent-screen to itself, if screen sources .bash_profile.
  4. Instead of starting ssh-agent in .bash_profile, you can consider connecting with ssh -A (to use agent forwarding and make the remote machine use your agent).

After this setup, you can just use standard screen command. You'll only need to recreate existing sessions or manually set SSH_AUTH_SOCK inside them to the fixed location of step 2.

Credits to this website for the idea; I avoided using /tmp. This answer is similar but uses extra aliases.

0
2

Can you launch ssh-agent from an initscript instead of .bash_profile? For instance, I might put

su -c 'ssh-agent -s > ~/.ssh_agent_env' myusername

in the appropriate part of /etc/conf.d/local, although RHEL/Fedora probably uses a different system. As you pointed in your comment, terminal sessions will need to be able to connect to the agent, which is why that command creates the file .ssh_agent_env in the user's home directory. Then you can add

[ -f ~/.ssh_agent_env ] && source ~/.ssh_agent_env >/dev/null

in .bash_profile.

Another thing you could do is put the following in .bash_profile

ps -U myusername | grep -q ssh-agent || ssh-agent -s > ~/.ssh_agent_env
source ~/.ssh_agent_env >/dev/null

which will start ssh-agent only if it's not already running. Then you don't have to kill it.

As a slightly different alternative to the second suggestion, instead of checking for the existence of an ssh-agent process, you could check for the existence of the file ~/.ssh_agent_env,

[ -f ~/.ssh_agent_env ] || ssh-agent -s > ~/.ssh_agent_env
source ~/.ssh_agent_env >/dev/null

If everything works properly, there shouldn't be any significant difference between the two ways.

2
  • The initscript idea is interesting -- basically, just start it at system startup for all users who want it? That could work. We don't have a lot of users who would care. Whether or not that's significantly better than not having a passphrase at all is an interesting question, since I suspect that means you'd only have to enter it once per machine restart. Hmm. Both that and the second suggestion rely on new terminal sessions being able to connect to the ssh-agent if it's already running. I'm not completely sure it's that easy, but I haven't tried yet. Thanks for the ideas!
    – Michael H.
    Jul 1, 2010 at 2:44
  • @khedron: Yep, but you'd have to put one line in /etc/conf.d/local (or your equivalent) for each user who uses the agent, to launch a separate ssh-agent process per user. If, as you say, you don't have a huge number of users, that wouldn't be too bad. You raise a good point (which I forgot to consider) about terminal sessions attaching to the agent; see my edit to the answer.
    – David Z
    Jul 1, 2010 at 5:57
2

Check out keychain. It does all of the above. Look especially at the --clear and --timeout options.

2

A better approach is to use ssh agent forwarding (-A option). This allows the person using ssh to use keys from the ssh-agent running on the machine they are coming from, presumably the workstation they are actually sitting at.

1
  • 1
    This also allows an attacker that compromises your account to compromise accounts on other machines that that agent can access. I therefore try to keep ssh agent forwarding to a minimum.
    – Paul Price
    Sep 18, 2014 at 19:41
2

to follow up on ssh agent forwarding, you'll find that by default the forwarded ssh credentials won't be available to your screen session once you log out, log back in, and re-attach to your sesssion.

You can get around this, though, by having screen set the SSH_AUTH_SOCK environment variable to something well-known, and having that well-known location be updated to your current auth socket.

I use this shell function to re-enter screen and fix the ssh auth sock:

function sr () { 
    if [ ${+STY} = 1 ] ;then 
            echo already in screen\!
    else
            if [ "${SSH_AUTH_SOCK}x" != "x" ]; then
                    if [ ! -d /tmp/screenssh ]; then
                            mkdir /tmp/screenssh 
                    fi
                    rm -f /tmp/screenssh/socket
                    ln -s $SSH_AUTH_SOCK /tmp/screenssh/socket
                    echo $REMIP > /tmp/screenssh/remip
            fi                
            screen -DR
    fi
}

and I have this in my .screenrc:

setenv SSH_AUTH_SOCK /tmp/screenssh/socket

Hope this helps.

1
  • Using /tmp means that anybody else on the machine can clobber any of your files, if he knows their path. Sep 19, 2013 at 8:09
1

If I understood you right, you just want a screen session, which you detach and reattach sometimes but never again want to reenter the passwords for the ssh-agent (your private key password).

I think the easiest way is to start screen, than start ssh-agent with a sub shell and then stay in that sub shell. I.e.

screen
ssh-agent bash
ssh-add   # enter your password once

# some commands, some logins and logouts to remote servers via ssh public key

# <ctrl>+<a>, <ctrl>+<d> to detach screen
# you can now logout from this computer
# login again

# reattach to your screen
screen -r
# ssh-agent is still running
1
  • That's essentially what I do. I use screen to label one of the "tabs" inside as having the ssh-agent powers, and use that for svn work, etc. There's an extra wrinkle where I force ssh-agent to reauthorize after a number of hours, but yup, this is basically where I'm at.
    – Michael H.
    Feb 10, 2014 at 18:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .