如何通过ssh-agent转发gpg密钥?


29

我可以使用ssh配置文件来启用添加到ssh-agent的ssh密钥的转发。如何使用gpg键做同样的事情?


3
这两个答案都建议运行socat以在tcp端口上公开GPG代理unix套接字。但是,与unix套接字不同,TCP端口的访问控制级别不同。特别是,同一主机上的每个用户现在都可以连接到您的GPG代理。如果您使用的是单用户笔记本电脑,这可能是可以的,但是如果其他任何用户也可以登录同一系统(运行GPG代理的系统),则他们也可以访问您的GPG代理,从而带来严重的安全问题。让socat使用EXEC地址类型直接启动SSH可能是解决此问题的最佳方法。
Matthijs Kooijman 2014年

有关openssh 6.7+解决方案的另一种介绍,请参见2015.rmll.info/IMG/pdf/an-advanced-introduction-to-gnupg.pdf
phs

对我很有用。
ph

Answers:


16

编辑:此答案已过时,因为已在OpenSSH中实现了适当的支持,请参阅Brian Minton的答案。

SSH仅能转发隧道内的tcp连接。

但是,您可以使用类似socat通过TCP中继unix套接字的程序(例如,在客户端和服务器主机上都需要socat):

# Get the path of gpg-agent socket:
GPG_SOCK=$(echo "$GPG_AGENT_INFO" | cut -d: -f1)

# Forward some local tcp socket to the agent
(while true; do
    socat TCP-LISTEN:12345,bind=127.0.0.1 UNIX-CONNECT:$GPG_SOCK;
done) &

# Connect to the remote host via ssh, forwarding the TCP port
ssh -R12345:localhost:12345 host.example.com

# (On the remote host)
(while true; do
    socat UNIX-LISTEN:$HOME/.gnupg/S.gpg-agent,unlink-close,unlink-early TCP4:localhost:12345;
done) &

测试是否可以解决gpg-connect-agent。确保在远程主机上未定义GPG_AGENT_INFO,以使其退回到$HOME/.gnupg/S.gpg-agent套接字。

现在希望您所需要的只是一种自动运行所有这些的方式!


好的,当在配置文件中设置转发时,ssh代理密钥会自动转发。我会尝试的。
txwikinger 2010年

没错,ssh-agent也使用unix套接字,但是对此有特殊的支持(这里有点累:)不过,该解决方案仍然可以使用。
b0fh 2010年

1
对于此解决方案,如果我不在防火墙/ NAT之后,则可以通过端口12345公开访问我的gpg-agent。这应该在答案中提及。
乔纳斯·谢弗

我猜你最后的编辑解决了这个问题,乔纳斯?它只绑定到localhost现在。
2012年

这种失败对我来说从远程主机的以下说法gpg-connect-agentcan't connect to server: ec=31.16383 gpg-connect-agent: error sending RESET command: Invalid value passed to IPC。遥控器socat然后死亡。当地人socat死了socat[24692] E connect(3, AF=1 "", 2): Invalid argument该页面使我相信这将永远无法工作,因为代理不存储密钥(仅存储密码)。有没有人确认这可以正常工作?
2012年

17

从版本6.7开始,OpenSSH的新Unix域套接字转发可以直接执行此操作。

您应该能够执行以下操作:

ssh -R /home/bminton/.gnupg/S.gpg-agent:/home/bminton/.gnupg/S-gpg-agent -o "StreamLocalBindUnlink=yes" -l bminton 192.168.1.9

@DrewR。很高兴听您这么说。
Brian Minton 2015年

2
我找到了所需的关键细节:在遥控器上(私钥少)机,公共签署身份的密钥必须存在。本地gpg版本2.1.15 OS X,远程2.1.11 Linux。
ph

4

在新版本的GnuPG或Linux发行版中,套接字的路径可以更改。这些可以通过找到

$ gpgconf --list-dirs agent-extra-socket

$ gpgconf --list-dirs agent-socket

然后将以下路径添加到您的SSH配置中:

Host remote
  RemoteForward <remote socket> <local socket>

复制公钥的快速解决方案:

scp .gnupg/pubring.kbx remote:~/.gnupg/

在远程计算机上,激活GPG代理:

echo use-agent >> ~/.gnupg/gpg.conf

在远程计算机上,还修改SSH服务器配置并添加以下参数(/ etc / ssh / sshd_config):

StreamLocalBindUnlink yes

重新启动SSH服务器,重新连接到远程计算机-然后它将正常工作。


可以在以下位置找到更详细的教程,其中包括一些疑难解答:mlohr.com/gpg-agent-forwarding
MaLo

1
如果远程主机运行当前版本的Debian,则似乎systemctl --global mask --now gpg-agent.service gpg-agent.socket gpg-agent-ssh.socket gpg-agent-extra.socket gpg-agent-browser.socket需要运行该主机,以防止systemd启动窃取远程gpg-agent的套接字。根据bugs.debian.org/850982,这是预期的行为。
sampi

3

我必须做同样的事情,并且将脚本基于b0fh的解决方案,并进行了一些微小的修改:它捕获出口并杀死后台进程,并且使用“ fork”和“ reuseaddr”选项进行socat,从而节省了循环(并使背景socat完全可以杀死)。

整个过程一口气设置了所有转发,因此它可能更接近于自动设置。

请注意,在远程主机上,您将需要:

  1. 您打算用来签名/加密/解密内容的密钥环。
  2. 根据遥控器上gpg的版本,是一个伪GPG_AGENT_INFO变量。我用~/.gnupg/S.gpg-agent:1:1- 预填充我的第一个-gpg代理的PID(我将其伪称为“ init”,它一直在运行),第二个是代理协议版本号。这应该与在本地计算机上运行的计算机相匹配。

#!/bin/bash -e

FORWARD_PORT=${1:-12345}

trap '[ -z "$LOCAL_SOCAT" ] || kill -TERM $LOCAL_SOCAT' EXIT

GPG_SOCK=$(echo "$GPG_AGENT_INFO" | cut -d: -f1)
if [ -z "$GPG_SOCK" ] ; then
    echo "No GPG agent configured - this won't work out." >&2
    exit 1
fi

socat TCP-LISTEN:$FORWARD_PORT,bind=127.0.0.1,reuseaddr,fork UNIX-CONNECT:$GPG_SOCK &
LOCAL_SOCAT=$!

ssh -R $FORWARD_PORT:127.0.0.1:$FORWARD_PORT socat 'UNIX-LISTEN:$HOME/.gnupg/S.gpg-agent,unlink-close,unlink-early,fork,reuseaddr TCP4:localhost:$FORWARD_PORT'

我相信,还有一种解决方案仅涉及使用SSH命令调用(从远程主机连接回本地主机)-o LocalCommand,但我不太想知道如何在退出时方便地将其杀死。


您不是在最后一条命令中的socat前面缺少一些“ user @ host”参数吗?无论如何,即使解决了这个问题,当我远程尝试gpg-connect-agent时,在本地弹出“ socat [6788] E connect(3,AF = 2 127.0.0.1:0,16):连接被拒绝”对我来说还是失败。
David Faure

1

根据GnuPG Wiki,您必须将远程套接字转发S.gpg-agent.extra到本地套接字S.gpg-agent。此外,您需要StreamLocalBindUnlink在服务器上启用。
请记住,您还需要远程GnuPG上可用的公开密钥。

gpgconf --list-dir agent-socket分别gpgconf --list-dir agent-extra-socket在遥控器上使用以获取实际路径。


摘要

  1. 远程配置/etc/sshd_config

    StreamLocalBindUnlink yes
    
  2. 将您的公钥导入远程:

    gpg --export <your-key> >/tmp/public
    scp /tmp/public <remote-host>:/tmp/public
    ssh <remote-host> gpg --import /tmp/public
    
  3. 通过启用了gpg-agent转发的SSH连接的命令:(我的Debian的路径)

    ssh -R /run/user/1000/gnupg/S.gpg-agent:/run/user/1000/gnupg/S.gpg-agent.extra <remote-host>
    

@brian minton:如果不转发到额外的套接字,它对我不起作用。
doak

0

作为替代修改/etc/ssh/sshd_configStreamLocalBindUnlink yes,你可以改为防止需要更换插座文件的创建:

systemctl --global mask --now \
  gpg-agent.service \
  gpg-agent.socket \
  gpg-agent-ssh.socket \
  gpg-agent-extra.socket \
  gpg-agent-browser.socket

请注意,这会影响主机上的所有用户。

奖励:如何测试GPG代理转发是否有效:

  • 本地: ssh -v -o RemoteForward=${remote_sock}:${local_sock} ${REMOTE}
  • 检查一下 ${remote_sock} ssh的详细输出是否显示
  • 远程: ls -l ${remote_sock}
  • 远程: gpg --list-secret-keys
    • 您应该看到很多debug1来自ssh 的消息,显示转发的流量

如果这不起作用(对我而言不起作用),则可以跟踪GPG正在访问哪个套接字:

strace -econnect gpg --list-secret-keys

样本输出:

connect(5, {sa_family=AF_UNIX, sun_path="/run/user/14781/gnupg/S.gpg-agent"}, 35) = 0

在我的情况下,所访问的路径完全匹配${remote_sock}但是sshd尽管StreamLocalBindUnlink yes我添加了该套接字,我登录时并没有创建该套接字/etc/ssh/sshd_config。我是在登录时由systemd创建的。

(请注意,我太胆怯无法重启 sshd,因为我现在无法物理访问主机。service reload sshd显然这还不够...)

在Ubuntu 16.04上测试

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.