Forwarding gpg-agent to a remote system over SSH

GnuPG 2.1 enables you to forward the GnuPG-Agent to a remote system. That means that you can keep your secret keys on a local machine (or even a hardware token like a smartcard or on a GNUK).

You need at least GnuPG 2.1.1 on both systems.

GnuPG configuration

Edit your gpg-agent.conf to configure an extra socket. The extra socket is more restricted then the normal socket and Pinentry messages will differ when gpg-agent is accessed over this socket:

extra-socket /home/<user>/.gnupg/S.gpg-agent.extra

Replace <user> with your actual username.

GnuPG on the remote system

It is important to note that to work properly GnuPG on the remote system still needs your public keys. So you have to make sure they are available on the remote system even if your secret keys are not.

SSH Configuration

Note: With GnuPG >= 2.1.13 the location of the agents socket changed. To find out the name of the socket, always use:

gpgconf --list-dir agent-ssh-socket

OpenSSH >= 6.7

To your /.ssh/config you can add:

Host gpgtunnel
HostName server.domain 
RemoteForward /home/<user>/.gnupg/S.gpg-agent /home/<user>/.gnupg/S.gpg-agent.extra

If you can modify the servers settings you should put:

StreamLocalBindUnlink yes

Into /etc/ssh/sshd_config to enable automatic removal of stale sockets when connecting to the remote machine. Otherwise you will first have to remove the socket on the remote machine before forwarding works.

With StreamLocalBindUnlink yes you can connect with ssh gpgtunnel and just use GnuPG as usual.

Note: On Systems where systemd controls the directories under /var/run/user/<uid> it may be that the socket forwarding fails because /var/run/user/<uid>/gnupg is deleted on logout. To workaround this you can put gpgconf --create-socketdir in the startup script of your shell e.g. ~/.bashrc or ~/.zshrc.

OpenSSH < 6.7

Before OpenSSH 6.7 you need to use socat which is a bit more fragile and requires a loop to stay open.

# Execute locally
(while true; do
socat TCP-LISTEN:16668,bind= UNIX-CONNECT:$HOME/.gnupg/S.gpg-agent.extra;
done) &

# Connect to the remote system with Port forwarding.
ssh -R16668:localhost:16668 server.domain

# Connect the socket on the remote system
(while true; do
    socat UNIX-LISTEN:$HOME/.gnupg/S.gpg-agent,unlink-close,unlink-early TCP4:localhost:16668;
done) &

AgentForwarding (last edited 2016-10-24 08:27:06 by AndreHeinecke)