我想通过以下方式通过 Linux 跳转主机建立 SSH 隧道:
主机 A 基于 Windows,并具有用于与跳转主机(主机 B)进行身份验证的私钥。主机 B 是基于 Linux 的,并且具有不同的用户,该用户拥有用于与 DMZ 中的主机进行身份验证的私钥。主机 C 是基于 Windows 的,并且只能通过 SSH(或物理方式)从主机 B 访问。我已尝试过ssh -v -N user2@HostC -J user1@HostB -L [port]:HostC:[remote_port]
并且它可以工作,但只能使用密码,尽管在所有必要的主机上都有密钥,但它仍不断要求输入密码。
有人能帮忙解决这个问题吗?
PS 如果我在所有三个主机上使用相同的密钥对,它就会起作用,但出于安全原因,我想使用具有不同密钥对的不同用户。
答案1
初步说明
- 我不使用 Windows,但希望这不会有太大影响。
- 通常当我说“A”、“B”、“C”时,我的意思分别是“A 上的用户”、“B 上的用户 1”和“C 上的用户 2”。例如,“B 的密钥”表示“B 上可用的用户 1 的密钥”。这是为了简洁起见。
分析
这是如何-J
运作:
-J destination
首先与所描述的跳转主机建立 ssh 连接destination
,然后从那里建立到最终目的地的 TCP 转发,从而连接到目标主机。
这ssh -J user1@B user2@C
意味着不是相当于从 A 连接到 B,然后从 B 连接到 C。这相当于从 A 连接到 B,然后从 A 连接到 C(使用通过 B 转发的数据包)。B 上没有调用任何 SSH 客户端,因此允许您从 B 连接到 C 的密钥永远不会被使用。
解决方案
解决一般问题的最优雅的方法是让 C 接受(或一个)A 的密钥。你说:
如果我在所有三个主机上使用相同的密钥对,它就会起作用,但出于安全原因,我想使用具有不同密钥对的不同用户。
您可以使用不同的密钥对。我知道目前有一对密钥允许您从 A 连接到 B,还有一对单独的密钥允许您从 B 连接到 C。后者无关紧要。在 C 上授权 A 用于身份验证的任何密钥。它可能是旧密钥(已在 B 上授权的密钥);但它可能是专门为此连接创建的新密钥。
然后,当你ssh -J user1@B user2@C
在 A 上执行此操作时,你需要使用允许 A 连接到 B 的密钥和允许 A 连接到 C 的密钥。如果它们是不同的密钥,则需要同时使用它们。使用-i
如果需要的话,一次甚至两次。
替代解决方案
如果你从A连接到B之后,又真正从B连接到C的话,那么就可以使用已经注册的密钥。如果你想从A登录到C,那么应该是这样的:
# from A
ssh -t user1@B 'ssh user2@C'
(至少在 Linux 中;我不确定在 Windows 中引用是如何工作的)。
该命令ssh
在 B 上运行以连接到 C,因此它将使用 B 的密钥。
关于端口转发
您的原始命令使用了-N
和-L
,因此我理解唯一的目标是转发端口。您使用 A 到 C 的连接转发了端口,目的地也是 C;因此转发数据包的最后一段是从 C 上的 SSH 服务器到 C。或许从 B可以[remote_port]
到达。如果是这样,那么您不需要上述任何解决方案;您所需要的只是:
ssh -NL [port]:C:[remote_port] user1@B
这将使转发数据包的最后一段从 B 上的 SSH 服务器到 C。
如果最后一段航程必须从 C 到 C,那么行动方案取决于您选择的解决方案。
使用 A 的密钥授权给 C 的解决方案将允许您无需密码即可使用原始命令。
在 B 上运行的解决方案
ssh
将要求您将端口从 A 转发到 B,并将端口从 B 单独转发到 C。如下所示:ssh -L [port]:localhost:[relay_port] user1@B 'ssh -NL [relay_port]:C:[remote_port] user2@C'