通过 SSH,您可以将主机端的同一个私钥用于其他目的吗?

通过 SSH,您可以将主机端的同一个私钥用于其他目的吗?

我坐在一台计算机(“客户端”)上,使用我的私钥通过 SSH 连接到另一台计算机(“主机”)。

在主机上,我想使用存储在客户端计算机上的私钥克隆 Git 存储库。

在此处输入图片描述

这可能吗?(无需将私钥复制到主机。)

答案1

理论

您寻求的功能称为“SSH 代理转发”。它的工作原理如下:

  1. 您的本地计算机中正在运行一个代理(通常是一个程序ssh-agent)(或已从其他地方转发)。其他程序可以通过 UNIX 域套接字与代理通信,只要它们知道套接字的路径即可。正确的设置可提供正确的路径。
  2. 您可以根据需要向代理添加密钥(ssh-add …),或者像程序一样ssh添加他们使用的密钥(如果已配置为这样做)。
  3. 程序使用代理,而不是自己使用密钥。在我的这个答案我们会说他们要求代理人为他们解决难题。
  4. 您使用ssh -A本地连接到 SSH 服务器。您在服务器上运行的程序将能够与您的本地代理通信。您运行的任何知道如何与代理通信或ssh在后台使用的东西都将能够使用您的本地代理。代理在另一台计算机上的事实对他们来说并不重要。

启动代理

启动代理的方法有以下几种:

  1. 某些系统配置为在用户登录时启动代理。每个用户都有自己的代理。您的操作系统可能已经为您启动了代理。在 shell 中调用:

    env | grep '^SSH_AUTH_SOCK='
    

    非空输出表示SSH_AUTH_SOCK变量在环境中。它的值是(或至少应该是)允许程序与已运行代理进行通信的 UNIX 域套接字的路径。程序通过检查此确切的环境变量来查找套接字。变量的存在通常意味着代理正在运行并准备就绪。命名的变量SSH_AUTH_SOCK没有指向正在运行的代理的套接字是不正常的(出了问题)。

    如果您看到变量,则很可能有代理为您服务。继续阅读本回答的下一部分。

  2. 您可以通过在 shell 中调用来启动代理ssh-agent,但不要直接这样做。您希望程序能够在环境中找到正确的变量。Solessh-agent无法改变其父 shell 的环境。它打印旨在由 shell 评估的命令,因此 shell 本身会更改其自己的环境。您可以调用ssh-agent以查看它打印的内容,然后kill从输出中了解 PID,否则无用的代理将继续徒劳无功地运行。

    正确的命令是:

    eval "`ssh-agent`"
    

    有几件事需要解释:

    • eval可能很危险您可能听说过“eval是邪恶的”。在这里,这是正确的,因为ssh-agent它是少数专门设计用于eval安全使用的工具之一。

    • 不同的 shell 需要不同的语法。ssh-agent打印的内容需要与 shell 匹配。该工具打印在sh(和具有类似语法的 shell,例如 Bash) 或csh(和具有类似语法的 shell) 中有效的 shell 代码。ssh-agent通过检查变量来猜测正确的样式SHELL;如果它无法猜测,那么它将为 生成代码。您可以使用(对于-like shell) 或(对于-like shell)sh明确告诉它您需要什么样式。命令将类似于:-ssh-ccsh

      eval "`ssh-agent -s`"
      

      如果你想看到差异,请调用ssh-agent -sssh-agent -c而不调用eval。之后不要忘记kill正确的 PID。

    • 如今我们经常使用$()而不是反引号(这是正确的做法,$()更好),但$()在 中不起作用。此答案使用反引号在类似 shellcsh中同样有用sh类似csh贝壳。

    命令执行后eval …env | grep '^SSH_AUTH_SOCK='应该会显示一些内容。代理将一直运行,直到您将其杀死。杀死代理的最正确方法是:

    eval "`ssh-agent -k`"
    

    在与之前相同的 shell 中(如果需要,请使用-sxor -c)。没有eval该命令可以终止代理,但变量将保留在 shell 的环境中。无论您在此 shell 中执行什么操作,变量都将保留在继承它们并仍在运行的子进程的环境中。

  3. 启动代理的另一种方法是这样的:

    ssh-agent some_command …
    

    该工具将启动代理,然后some_command …在正确的环境中运行。some_command可能是bash,即如果你这样做:

    ssh-agent bash
    

    然后你会发现自己处于一个已经在环境中的交互式 Bash 中SSH_AUTH_SOCK(注意,如果你的原始 shell 也是 Bash,那么该命令可能看起来什么都没做;就像bash从 Bash 调用可能看起来没有任何操作,直到你exit发现你仍然在 Bash 中)。

    代理some_command终止时自动退出,无需维护。这种方法相当简单。

    如果你只需要一个本地代理,ssh那么some_command可能是ssh。在你的情况下,你需要ssh -A

    ssh-agent ssh -A …
    

    根据您要使用的密钥和 的配置ssh,上述方法可能是好主意,也可能不是。在某些情况下,您可能希望在运行之前对代理执行某些操作ssh -A(例如添加密钥,见下文)。


为代理添加密钥

当代理启动时,它没有任何私钥。如果您发现由操作系统启动的代理,理论上操作系统可能不仅启动了代理,还添加了一些密钥。使用ssh-add或按在 中设置ssh时添加密钥。AddKeysToAgentssh_config

在可以访问代理的 shell 中(SSH_AUTH_SOCK在环境中,代理正在运行)调用:

ssh-add -l

查看代理所代表的密钥(身份)。可能没有。要添加密钥,请运行:

ssh-add path/to/key

注意ssh-add,不带参数会探测一些标准路径名并添加找到的文件。请参阅man 1 ssh-add了解详情。

如果AddKeysToAgent已设置ssh_config(默认情况下未设置)或者您在命令行中请求它,ssh它本身将添加它使用的密钥。这意味着如果您想使用相同的密钥向服务器进行身份验证,然后稍后在服务器上进行身份验证,则不需要ssh-add。您可以执行以下操作:

# with agent already running
ssh -A -o AddKeysToAgent=yes …

这也适用于指定的键-i。这些情况允许您ssh在一个命令中运行代理和(上一节末尾提到的方法):

# already running agent (if any) is irrelevant
# we are starting a new agent
ssh-agent ssh -A -o AddKeysToAgent=yes …

调用ssh

相关选项是-A。从man 1 ssh

-A
允许转发来自身份验证代理(例如)的连接ssh-agent(1)。 也可以在配置文件中按主机指定此功能。

(配置文件中的关键字是ForwardAgent

服务器可能允许或不允许转发。AllowAgentForwardingDisableForwarding参阅man 5 sshd_config

被警告:

应谨慎启用代理转发。能够绕过远程主机上的文件权限(对于代理的 UNIX 域套接字)的用户可以通过转发的连接访问本地代理。攻击者无法从代理获取密钥材料,但他们可以对密钥执行操作,使他们能够使用加载到代理中的身份进行身份验证。[…]

如果服务器允许转发,并且已将正确的密钥添加到本地代理,那么-A您只需将其添加到ssh用于连接服务器的命令中即可。它可能很简单:

ssh -A user@server

并且使用ForwardAgent yesin ssh_config(或在您的~/.ssh/config) 您甚至不需要-A在命令行中,纯ssh user@server就可以了。


服务器情况

如果您的本地ssh -A …为您提供了一个交互式远程 shell,那么您可以使用与我们之前(本地)使用的相同的命令,现在在服务器上:

# on the server
env | grep '^SSH_AUTH_SOCK='

如果转发成功,您将发现变量已设置。它就像ssh-agent正在运行一样,但实际上是 SSH 服务器监听套接字并中继到您的本地ssh-agent。使用套接字的程序并不关心。您甚至可以进一步转发代理(从ssh -A服务器转发到另一台计算机)。

只需使用ssh或另一个能够与代理通信的命令即可。它应该找到套接字并与本地通信ssh-agent

ssh-add没有什么不同。这并不明显,但如果您ssh-add在服务器上使用来添加一些密钥,那么该工具实际上会从服务器添加密钥(而不是告诉您的本地ssh-agent打开具有相同路径的本地文件)。您可以断开与服务器的连接,而您的本地代理将继续持有添加的密钥。因此,本地ssh-agent不仅允许您在服务器上使用本地密钥;它还允许您使用来自服务器的密钥从本地连接到任何地方。但这有很大的不同。ssh-agent需要存储一些添加密钥的表示,即使只是在内存中。本地ssh-add与本地对话ssh-agent不会使本地密钥离开本地计算机。远程ssh-add与本地对话ssh-agent会将远程密钥复制到本地内存中。

如果您的本地ssh -A …指定了要在服务器上运行的命令(而不是交互式 shell),则代理转发机制不会发生任何变化。远程命令将SSH_AUTH_SOCK在环境中找到,并且能够与您的本地进行通信ssh-agent


可能出现的问题(已解决)、有趣的案例


文档


其他

相关内容