ssh-agent-switcher is a daemon that proxies SSH agent connections to any valid
forwarded agent provided by sshd. This allows long-lived processes such as
terminal multiplexers like tmux
or screen
to access the connection-specific
forwarded agents.
More specifically, ssh-agent-switcher can be used to fix the problem that arises in the following sequence of events:
- Connect to an SSH server with SSH agent forwarding.
- Start a tmux session in the SSH server.
- Detach the tmux session.
- Log out of the SSH server.
- Reconnect to the SSH server with SSH agent forwarding.
- Attach to the existing tmux session.
- Run an SSH command.
- See the command fail to communicate with the forwarded agent.
The ssh-agent-switcher daemon solves this problem by exposing an SSH agent
socket at a well-known location, allowing you to set SSH_AUTH_SOCK
to a path
that does not change across different connections. The daemon then looks for
a valid socket every time it receives a request and forwards the request to the
real forwarded agent.
ssh-agent-switcher is written in Go and has no dependencies. You can build it with the standard Go toolchain and then install it with:
go build
mkdir -p ~/.local/bin/
cp ssh-agent-switcher ~/.local/bin/
Or you can use Bazel:
bazel build -c opt //:ssh-agent-switcher
mkdir -p ~/.local/bin/
cp bazel-bin/ssh-agent-switcher_/ssh-agent-switcher ~/.local/bin/
Extend your login script (typically ~/.login
, ~/.bash_login
, or ~/.zlogin
)
with the following snippet:
if [ ! -e "/tmp/ssh-agent.${USER}" ]; then
if [ -n "${ZSH_VERSION}" ]; then
eval ~/.local/bin/ssh-agent-switcher 2>/dev/null "&!"
else
~/.local/bin/ssh-agent-switcher 2>/dev/null &
disown 2>/dev/null || true
fi
fi
export SSH_AUTH_SOCK="/tmp/ssh-agent.${USER}"
ssh-agent-switcher is intended to run under your personal unprivileged account and does not cross any security boundaries. All this daemon does is expose a new socket that only you can access and forwards all communication to another socket to which you must already have access.
Do not run this as root.