ssh-agent

3 minute read

Updated:

It’s common to use public key infrastructure (PKI) with SSH. The keys used can be very long and cryptographically secure. It’s much preferred over authentication with username and password.

An ssh-agent is often employed to assist in these efforts.

Why Use PKI

There are clear benefits to using PKI over using passwords.

Public Key

Part of the PKI is a public key that is not secret. It is generated and freely distributed without security concern.

Remote servers use this public key as part of the authentication scheme. If they are compromised, there’s little risk because the public key was not secret. You’re not beholden to the poor security practices of an individual.

Middlemen are given this public key. These can be programs or website that act as intermediary. They aren’t given the keys to the castle.

Private Key

The private key is a secret file. It’s in a single place, which makes securing it a bit easier. It never leaves the castle, unlike a password.

You can encrypt/sign data locally and send it to the remote. The remote can verify authenticity with the public key.

Or the remote can sign/encrypt data and send it to you. You can verify authenticity.

The secret never leaves the castle.

ssh-agent

Cool, so we’re on board with using keys instead of passwords. What’s next?

You need to unlock a private key to use it. Even though it’s stored locally, it’s encrypted at rest. Whoever has access to your machine will still need the password to make use of it. It’s 2FA, where the keyfile is possession and the passphrase is knowledge.

Every ssh request will need to use the key, which will require unlocking, every single time. This gets annoying real fast and ssh-agent helps here.

Why Use An Agent

An ssh-agent is a long-lived process that maintains state. You unlock the key once and the agent will be able to handle any request in the future.

SSH clients will communicate with the agent through a socket. Anyone with permission to access the socket can use the unencrypted key. On a local machine, this is managed through user permissions: root is the only other user that has access. This is the same security concern as “root access”, root user can circumvent anything since they have complete control over the host.

Agent Forwarding

Agents can be forwarded as well, further increasing their utility. On the remote server, a remote agent is available on a socket. When the remote server needs to make further SSH connections, it uses the forwarded agent. Information gets sent back to the local machine and only the result is sent back to the remote. In this manner, the unencrypted private key never leaves the local machine.

The forwarded agent socket shares the identical security issues on the remote host: superusers on the remote host will have access to the socket. You will need to trust the remote host if you want to use forwarding. Since we’re talking about authentication, this effectively limits this to hosts that you 100% control. A superuser will have permission to use the socket to masquerade and authenticate ssh connections as you.

While they cannot access the unencrypted key (kept local), they basically don’t need to as the forwarded agent serves the same purpose. An analogy is that you can “revoke” this at anytime, by closing the ssh connection with the forwarding.

Personally, I use key forwarding between my own devices to keep things simple. In the past at work, I would create a different key on a bastion/dev box for moving around within the local network. This key would live in ssh-agent, which is long-lived. There’s no more risk of abusing this agent, since it’s only purpose is moving around and an admin can already do that. Then I forward a key that’s used for other auth purposes (github). This socket would only be alive while I’m connected, and only to the bastion/dev box, which is where I do work and push changes.

Not exactly bulletproof but it limits needless exposure.

MacOS

MacOS comes with the ability to read from the OS keychain. The passphrase to the private key can be accessed from here. On every ssh request, the private key is unlocked.

This is entirely transparent as keeps ssh usage stateless. The keychain is unlocked when you login and unlock the OS. You don’t have need for an ssh-agent.

To use this, the ssh config is:

Host github.com
  IgnoreUnknown UseKeychain
  UseKeychain yes

WSL

WSL does not yet have integration to read the Windows keyring. So this is similar to vanilla ssh-agent setups.

Host github.com
  AddKeysToAgent yes

This will automatically startup a ssh-agent process and add the key to it.