SSH代理已解释

2020-05-20 09:19:29

tl;dr SSH代理是OpenSSH的核心部分。在这篇文章中,我将解释什么是代理,如何使用它,以及它是如何保护您的密钥安全的。我还将介绍代理转发及其工作原理。我将帮助您降低使用代理转发时的风险,并且我将与您分享通过堡垒访问内部主机时可以使用的代理转发替代方案。

SSH代理是SSH的密钥管理器。它将您的密钥和证书保存在内存中,未加密,可供ssh使用。它使您不必在每次连接到服务器时都键入密码短语。它在系统的后台运行,独立于ssh,通常在重新引导后第一次运行ssh时启动。

存储在代理中的私钥只能用于一个目的:签署消息。

但是,如果代理只能对消息进行签名,那么SSH如何加密和解密流量呢?

当第一次了解公钥和私钥时,自然会认为SSH使用这些密钥对流量进行加密和解密。我也是这么想的。但事实并非如此。SSH密钥对仅用于初始握手期间的身份验证。

例如,从服务器的角度来看,下面是如何在SSH握手期间验证用户密钥的:

服务器生成并发送一条简短的随机消息,要求客户端使用私钥对其签名。

客户端要求SSH代理对消息进行签名,并将结果转发回服务器。

服务器现在有证据证明客户端拥有他们的私钥。

稍后在握手过程中,将生成一组新的临时对称密钥,并用于加密SSH会话流量。这些密钥甚至可能不会持续整个会话;“更新密钥”事件定期发生。

SSH使用Unix域套接字通过SSH代理协议与代理通信。大多数人使用OpenSSH附带的ssh-agent,但也有多种开源替代方案。

代理协议非常简单,人们可以在一两天内编写一个基本的SSH代理。它只有几个主要操作:

🤔什么是受限密钥?它通常是一个使用期限有限的密钥,或者在使用时需要明确的用户确认。

ssh-add命令是SSH代理的网关。它执行除签名之外的所有这些操作。当您在不带任何参数的情况下运行ssh-add时,它将扫描您的主目录以查找一些标准密钥,并将它们添加到您的代理中。默认情况下,它查找:

MacOS附带的ssh-agent可以将密钥的密码短语存储在MacOS密钥链中,这使得在重新引导后将密钥重新添加到代理变得更加容易。根据您的密钥链设置,您可能仍需要在重新启动后解锁密钥链。要在密钥链中存储密钥密码短语,请运行ssh-add-K[key filename]。密码短语通常存储在“Local Items”密钥链中。SSH代理将根据需要自动使用这些存储的密码短语。

SSH的代理转发功能允许您的本地SSH代理通过现有的SSH连接到达,并在更远的服务器上透明地进行身份验证。例如,假设您通过SSH连接到一个EC2实例,并希望从那里克隆一个私有的GitHub存储库。如果没有代理转发,您必须将GitHub私钥的副本存储在EC2主机上。通过代理转发,EC2上的SSH客户端可以使用本地计算机上的密钥向GitHub进行身份验证。

首先,我们来了解一下背景情况。SSH连接可以有多个通道。这里有一个常见的例子:到堡垒主机(跳箱)的交互连接在一个频道上运行。当为连接启用代理转发时(通常使用ssh-A),会在后台打开第二个通道,将任何代理请求转发回您的本地计算机。

从ssh';的角度来看,远程ssh代理和本地ssh代理之间没有区别。SSH始终查看$SSH_AUTH_SOCK环境变量以查找代理的Unix域套接字。在启用代理转发的情况下连接到远程主机时,sshd将创建链接到代理转发通道的远程Unix域套接字,并导出指向该套接字的$SSH_AUTH_SOCK。

当您将ssh-agent的Unix域套接字转发到远程主机时,会产生安全风险:在远程主机上具有root访问权限的任何人都可以通过该套接字谨慎地访问您的本地SSH代理。他们可以使用您的密钥在网络上的其他计算机上模拟您。

我们建议不要这么做。相反,请仅在需要的情况下使用代理转发。SSH-A为单个会话打开代理转发。

定期锁定您的ssh代理。ssh-add-x使用密码锁定代理,ssh-add-X将其解锁。当您通过代理转发连接到远程主机时,没有人能够在没有密码的情况下偷偷进入您的代理。

使用另一个SSH代理,该代理在使用时会提示您。Sekey在MacOS上使用Touch ID在MacBook Pro的安全飞地中存储密钥。

您不需要代理转发即可通过堡垒访问内部主机。对于此用例,ProxyJump是一个安全得多的替代方案。

当您想要通过堡垒主机(跳箱)时,您真的不需要代理转发。更好的方法是使用ProxyJump指令。

ProxyJump不通过单独的通道转发代理,而是将本地SSH客户端的标准输入和输出通过堡垒转发到远程主机。下面是它的工作原理:

运行ssh-J bastion.example.com cloud.computer.Internal,通过bastion.example.com堡垒主机连接到cloud.computer.Internal。Internal是一个可以在bastion.example.com上使用DNS查找来查找的主机名。

连接之后,堡垒上的sshd将连接到cloud.computer.Internal,并将该连接移交给您的本地SSH客户机。

您可以将其视为SSH会话中的SSHing;只是ssh程序从不在堡垒上运行。相反,sshd连接到cloud.computer.Internal,并将该连接的控制权(标准输入和输出)返回给本地SSH,然后本地SSH执行第二次握手。

假设我的堡垒主人是bastion.example.com。我可以这样设置我的~/.ssh/config文件:

然后,我只需运行ssh cloud.computer.Internal即可通过堡垒连接到内部目的地,而无需代理转发。

较早版本的SSH和SSHD(7.2之前,于2016年发布)不支持ProxyJump。但是您可以使用ProxyCommand和Netcat执行等效操作。下面是一个例子:

这里的神奇之处在于,SSH本身就是您正在使用的SSH代理。nc%h%p部分只是在端口22上打开到cloud.computer.Internal的原始套接字连接。父ssh命令的标准I/O通过管道直接传输到ProxyCommand,以便父ssh可以通过代理连接向内部主机进行身份验证。

我们喜欢谈论所有的事情宋承宪。如果您有任何问题或反馈,请在Twitter上联系我们!