我想为 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
修复了什么?
前面
:
没有10022
任何内容的 定义了一个空的bind_address
。如果没有它,HostA 上的 SSH 服务器将仅绑定到环回接口,即localhost:10022
在 HostA 上,无法从外部访问。空bind_address
表示“所有接口”。请参阅我对相关问题的回答了解详情。远程转发的目标在本地计算机(在本例中为 HostB)上解析。要从 HostB 本身访问 HostB 上的 SSH 服务器,很可能
localhost
就足够了。这是因为 SSH 服务器通常会监听其环回接口。指向 HostB 的另一个地址可能也有效,但localhost
或是127.0.0.1
最吻-在这种情况下。指定目标时,您不能指定任何用户。我的意思是,
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:10022
HostB 的地址并简单地使用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 进行连接,那么您可能希望避免这种情况。那么强烈建议使用第一种方法。