SSH agent forwarding lets you use your local SSH keys to authenticate to remote servers without copying your private keys to those servers.

Here’s a simple setup:

# On your local machine
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_forward -C "forwarding_key"

# Add the key to the agent
ssh-add ~/.ssh/id_rsa_forward

# On a remote server (e.g., bastion)
ssh -A user@remote_host

# Now, from the remote server, you can SSH to another server
# using your local key, without the private key being on remote_host
ssh another_user@another_host

This works by having the ssh-agent process on your local machine hold your decrypted private keys. When you use ssh -A, your local SSH client tells the ssh-agent to listen on a special Unix domain socket. The remote SSH client, when connecting, uses this socket to forward authentication requests back to your local ssh-agent. The agent then performs the cryptographic operations using your private key and sends the result back. This way, your private key never leaves your local machine.

The problem this solves is the secure management of SSH keys across multiple servers. Without agent forwarding, you’d either have to copy your private keys to every server you want to access from, which is a massive security risk, or set up complex certificate authorities. Agent forwarding provides a convenient and relatively secure way to hop between machines.

Internally, when ssh -A is used, the ssh client establishes a connection to the remote server and then instructs the local ssh-agent to create a forwarding agent protocol connection. This protocol allows the remote ssh client to request authentication from the local ssh-agent as if it were running locally on the remote machine. The ssh-agent listens on a Unix domain socket, and the SSH_AUTH_SOCK environment variable points to this socket. When agent forwarding is enabled, the remote ssh client sets the SSH_AUTH_SOCK environment variable to point to a socket that acts as a proxy back to your local ssh-agent.

The key levers you control are:

  • ssh-add: This command adds your private keys to the running ssh-agent process. You can specify a key file with -f. If you don’t specify a file, it defaults to your standard keys (~/.ssh/id_rsa, ~/.ssh/id_dsa, etc.).
  • ssh -A: This flag enables agent forwarding for the current SSH connection.
  • ssh-agent: This is the daemon that manages your keys. It’s often started automatically by your desktop environment or can be started manually. You can check if it’s running by looking for the SSH_AUTH_SOCK environment variable.
  • ~/.ssh/config: You can configure agent forwarding per host in your ~/.ssh/config file, so you don’t have to remember -A every time.
Host bastion
    Hostname bastion.example.com
    User myuser
    ForwardAgent yes

Host internal-server
    Hostname internal-server.example.com
    User anotheruser
    ForwardAgent yes

With this configuration, ssh bastion will automatically enable agent forwarding.

The most surprising thing about agent forwarding is that the remote server never sees your private key, but it can still authenticate using it. This is achieved through a clever relay mechanism where the remote SSH client sends authentication challenges to your local ssh-agent, which then signs the challenges locally and sends the signed response back. The security of this relies entirely on the security of your local machine and the ssh-agent process. If your local machine is compromised, or if your ssh-agent is left running with keys that have no passphrase, then your forwarded keys are at risk.

The next concept you’ll run into is managing multiple SSH keys and deciding which ones to add to your agent for different environments.

Want structured learning?

Take the full Ssh course →