ssh agent 传递密钥而不暴露
agent 转发并不等于 agent。转发是请远端主机上的 sshd 自己开一个套接字,并把那边的 SSH_AUTH_SOCK 指过去,于是那台机器上的程序可以回头找你家里的 agent 签名。远程自始至终没有拿到密钥,它也根本不需要拿到:它拿到的是这份能力的完整使用权。 这是穿过堡垒机抵达内网机器的常规做法,同时也意味着路径上每一跳都分到了这份能力。多数伸手去拿 -A 的人,真正想要的是 ProxyJump——它只转发 TCP,把 agent 留在本机。 两者容易被混为一谈,是因为它们用的是同一套协议、同一个 SSH_AUTH_SOCK 变量,区别只在于那只套接字落在哪台机器上。agent 留在本机,它就是你的私钥保险箱;套接字出现在远端,它就是一张那台机器上任何程序都能使用的通行证。 远程拿到的是套接字,不是密钥 ssh_config(5) 对这笔交易毫不含糊。ForwardAgent 接受 yes、no(默认值)、一个明确的套接字路径,或某个环境变量的名字;手册警告说,能够在远端绕过该 agent 套接字文件权限的用户,可以经由这条转发连接访问你本地的 agent。更要紧的是紧接着的那句:攻击者无法从 agent 取得密钥材料,但可以对密钥执行操作,从而用已装载的身份完成认证。 本文的实测正好呈现了这个形状。一个只拿到 SSH_AUTH_SOCK、既没有密钥文件也没有口令的第三方进程,列出了身份并拿到了一枚 88 字节的签名。这就是转发交给某一跳的全部能力。 转发是逐跳选择的 能签名的机器集合,恰好就是那些以启用转发的方式运行 ssh 的跳数。ssh -A bastion 把 agent 暴露给 bastion;从那里再 ssh -A build-box,build-box 也一并拿到;而 ssh build-box 不带 -A,链条就止步于 bastion。没有任何一跳会意外地级联下去,但也没有任何东西会提醒你。 ...