Skip to content

Instantly share code, notes, and snippets.

@smblott-github
Last active December 26, 2018 10:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save smblott-github/95d96ed8b78ea4719b85d64f50755b71 to your computer and use it in GitHub Desktop.
Save smblott-github/95d96ed8b78ea4719b85d64f50755b71 to your computer and use it in GitHub Desktop.
Maintain the correct SSH agent config when using tmux remotely (after detach, reattach)
#!/bin/sh
# This goes in ~/.ssh/rc.
# It adds a symlink to the new $SSH_AUTH_SOCK under ~/.ssh/ssh-auth-socks/.
# The symlink is named after the current /dev/pts entry, so that we can find the correct link/agent to use later.
if [ -n "$SSH_TTY" ] && [ -n "$SSH_AUTH_SOCK" ]
then
mkdir -p $HOME/.ssh/ssh-auth-socks
ln -sf $SSH_AUTH_SOCK $HOME/.ssh/ssh-auth-socks/${SSH_TTY##*/}
fi
#!/usr/bin/zsh
# This goees in your ~/.zshrc (or equivalent).
# It checks - before each command execution - that we are using the correct $SSH_AUTH_SOCK.
re-ssh-agent ()
{
[[ -z $TMUX ]] && return
local -a clients
clients=( $( tmux list-clients -F "#{client_activity}-#{client_tty}" ) )
clients=( ${(On)clients} )
[[ $#clients == 0 ]] && return
local client=$clients[1]
local socket=$HOME/.ssh/ssh-auth-socks/$client:t
if [[ -S $socket ]] && [[ $SSH_AUTH_SOCK != $socket ]]
then
export SSH_AUTH_SOCK=$socket
print SSH_AUTH_SOCK=$SSH_AUTH_SOCK >&2
fi
}
preexec ()
{
re-ssh-agent
}
@smblott-github
Copy link
Author

Problem...

All of this assumes that you're using SSH agent forwarding.

  1. SSH from client A to server S and fire up tmux. Detach from tmux. SSH from A to S again and reattach to the previous TMUX session. You end up using a stale SSH agent socket.

  2. As before, but also SSH from client B to the same server (and attach to the tmux session). If you're not careful, B ends up either with a stale SSH agent socket, or using client A's SSH agent (which seems incorrect to me).

The solution here isn't perfect, but it handles my own use cases satisfactorily.

The approach is:

  1. Put the file named rc in ~/.ssh (so, ~/.ssh/rc). This creates a symbolic link for every new SSH connection associating the current $SSH_TTY with its $SSH_AUTH_SOCK. The link looks something like this:
    /home/blott/.ssh/ssh-auth-socks/3 -> /tmp/ssh-hQpxD30VMU/agent.20951
  1. Put the zshrc fragment somewhere in your ~/.zshrc. This checks for the SSH agent associated with the current tmux client, and sets $SSH_AUTH_SOCK accordingly (if necessary).

Here's a screenshot of a single shell process swapping the SSH agent it's using as I flick between two different connections to the same remote tmux session...

image

(This is for zsh, but it shouldn't be too hard to translate it to bash.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment