SSH agent forwarding and tmux done right
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 Rust so you will need a standard Rust toolchain in place. See rustup.rs for installation instructions.
Then use make to build and install the binary in release mode along with its
manual page and supporting documentation:
make install MODE=release PREFIX="${HOME}/.local"You may also use Cargo to install this program under ${HOME}/.cargo/bin, but
the recommended method is to use make install as shown above because Cargo
will not install anything other than the program binary:
cargo install ssh-agent-switcherExtend your login script (typically ~/.login, ~/.bash_login, or ~/.zlogin)
with the following snippet:
~/.local/bin/ssh-agent-switcher --daemon 2>/dev/null || true
export SSH_AUTH_SOCK="/tmp/ssh-agent.${USER}"For fish, extend ~/.config/fish/config.fish with the following:
~/.local/bin/ssh-agent-switcher --daemon &>/dev/null || true
set -gx 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.