通过服务器通过 SSH 隧道连接到本地网络机器

通过服务器通过 SSH 隧道连接到本地网络机器

我想为 centos 机器的外部管理员准备一个 ssh 连接。

按照以下设置:

  • HostA:具有静态 IP 地址的服务器
  • HostB:本地 CentOS 机器
  • HostC:外部管理系统

连接布局: HostC > HostA > (Router) > HostB

我在 HostB 上尝试了以下命令:

ssh -R Port:user@HostB:22 user@HostA

ssh user@HostB -p Port # --> Timeout here

我不想碰路由器,我想这并非绝对必要。到 HostA(linode 服务器)的 ssh 连接工作正常。Netstat 显示正在PORT监听。但第二个命令超时了。可能是什么原因?

如何从 HostC 连接,以下命令有效吗?

ssh -t HostA 'ssh HostB -p Port'

其他条件:

  • 我已经GatewayPorts yes在HostA设置了。
  • HostA 仅允许通过密钥文件进行连接。
  • HostA 已经知道 HostB 和 HostC 的公钥。
  • HostB 使用 ssh 默认配置
  • 所有机器上的 Ufw 防火墙(端口 22 和 10022 开放)

有没有更简单的方法可以保存连接,而不必担心路由器?

答案1

至少有两个解决方案ssh -R,你似乎混淆了它们的部分。没有什么是错误的。


在HostA上监听,向外开放的端口

这几乎是这个问题的重复:通过反向 SSH 隧道和 URL 访问本地主机 Web 服务器我相信这里的主要问题是一样的,我对另一个问题的回答适用但这还不够。

你的命令如下:

# on HostB
ssh -R 10022:user@HostB:22 user@HostA

它应该是这样的:

# on HostB
ssh -R :10022:localhost:22 user@HostA

修复了什么?

  1. 前面:没有10022任何内容的 定义了一个空的bind_address。如果没有它,HostA 上的 SSH 服务器将仅绑定到环回接口,即localhost:10022在 HostA 上,无法从外部访问。空bind_address表示“所有接口”。请参阅我对相关问题的回答了解详情。

  2. 远程转发的目标在本地计算机(在本例中为 HostB)上解析。要从 HostB 本身访问 HostB 上的 SSH 服务器,很可能localhost就足够了。这是因为 SSH 服务器通常会监听其环回接口。指向 HostB 的另一个地址可能也有效,但localhost或是127.0.0.1-在这种情况下。

  3. 指定目标时,您不能指定任何用户。我的意思是,HostB作为目标可能有效,但不是user@HostB。在您的情况下,后者似乎无法正常工作,因为只有当有人实际使用隧道时,地址才会被解析。您从未成功使用过隧道。如果您成功使用过,则该ssh过程(在 HostB 上使用 的过程-R)将产生:

    connect_to user@HostB: unknown host (Name or service not known)
    

    至少这是我的 Debian 10 中的 OpenSSH 所说的。

笔记:

  • 考虑-N-N -f选项(参见man 1 ssh);或autossh
  • GatewayPorts yes在 HostA 上的 SSH 服务器配置是正确的。
  • HostB 上的防火墙不会阻止与环回接口的连接,无需配置。TCP 端口是否22向外界开放无关紧要。
  • HostA 上的防火墙应该打开 TCP 端口10022(当然22还有 SSH 服务器监听的任何端口)。

然后从互联网上你可以像这样连接:

# on HostC or wherever
ssh -p 10022 userB@HostA

请注意,HostC 的命令没有以任何方式指定 HostB, userB应该在 HostB 上有效,并且应该使用 的凭证userB@hostB。如果要使用基于密钥的身份验证,HostC 应该持有密钥;HostA 上的密钥无关紧要。这就像 HostB 的 SSH 服务器正在监听HostA:10022。该地址属于 HostA,但可以到达在 HostB 上运行的 SSH 服务器。隧道本身是透明的。我的意思是您可以忘记隧道的存在,将其视为HostA:10022HostB 的地址并简单地使用ssh语法。例如以下命令:

# on HostC or wherever
ssh -p 10022 userB@HostA hostname

将(尝试)hostname在 HostB 上运行。


在 HostA 上监听 HostA 可用的端口

如果你这样做:

# on HostB
ssh -R :10022:localhost:22 user@HostA

然后 HostA 上的 SSH 服务器将监听所有接口,包括 HostA 的环回接口。如果您执行的操作与您尝试的操作更类似:

# on HostB
ssh -R 10022:localhost:22 user@HostA

:(注意之前没有10022)那么服务器将只监听环回接口。无论如何,您都应该能够从 HostA 连接到 HostB,如下所示:

# on HostA
ssh -p 10022 userB@localhost

其中userB在 HostB 上有效。这意味着可以这样做:

# on HostC or wherever
ssh user@HostA    # or any other userA valid on HostA
# now we're on HostA
ssh -p 10022 userB@localhost

或者用一行来表示:

# on HostC or wherever
ssh -t userA@HostA 'ssh -p 10022 userB@localhost'

与第一种方法的区别:

  • 在某些情况下,需要-t明确使用。
  • HostA 上的合理防火墙不应阻止与环回接口的连接,无需配置。TCP 端口是否10022向外界开放无关紧要。这意味着即使您不是 HostA 上的管理员,该方法也可能有效。此外……
  • GatewayPorts(非管理员无法调整的另一件事)不一定需要yes
  • 到 HostB 的连接来自 HostA。如果要使用基于密钥的身份验证,则 HostA 应该持有密钥。有一个转发身份验证代理连接的概念,因此 HostC 可以持有密钥。或者,可以从 HostC 到 HostB 创建隧道,因此以后 HostC 可以通过两个链接的隧道到达 HostB 的 SSH 服务器并使用自己的密钥。我不会详细说明。
  • 必须有对 HostA 的 SSH 访问权限。如果不是您要从 HostC 进行连接,那么您可能希望避免这种情况。那么强烈建议使用第一种方法。

相关内容