通过跳转主机、ssh_config 文件和仅“ssh targethost”进行 SSH 端口转发

0xC*_*22L 7 openssh ssh-tunneling port-forwarding

注意:我使用的 OpenSSH 客户端都是7.2 版,所以不可RemoteCommand用。

假设以下设置:

  1. 机器foo是一个跳转主机,并bar通过其提供对主机的访问localhost:10022
  2. bar位于网络内,我们可以在其中访问主机rdp并访问其 RDP 端口 (3389)。我实际上rdp在我的命令行和配置中给出了 IP ,但我认为只要名称查找有效,使用它的名称是合法的。为简洁起见,我在rdp这里使用。

现在的目标是rdp:3389通过连接到barvia jump hostfoo并将其转发到localhost:33389我正在调用的本地机器上来获得访问权限ssh bar

[local:33389] --> {foo} --> {bar} --> [rdp:3389]
Run Code Online (Sandbox Code Playgroud)

插曲

我以前用 PuTTY 解决了这个问题,如下所示:

  1. 创建foo与本地转发的连接并配置本地转发-L 33389:localhost:33389,从而将localhost:33389本地计算机绑定到localhost:33389on foo
  2. 使用下面的远程命令来携带端口转发到网络内其bar位于由通过ssh -L 33389:rdp:3389 -A bar
  3. Host bar foo内部配置.ssh/config为连接到localhost:10022并最终bar通过跳转主机。

PuTTY 配置就像一个魅力,但它依赖于要执行的远程命令。虽然外壳别名将是解决此问题的一种方法,但我想知道是否有办法将所有内容保存在ssh_config(5)我的客户端使用的内部,使用ProxyCommand?


上面 PuTTY 配置的粗略等价物是这样的:

ssh -L 33389:localhost:33389 foo ssh -t -L 33389:rdp:3389 -p 10022 localhost
Run Code Online (Sandbox Code Playgroud)

或者,所提供Host bar的配置上foo要经过localhost:10022foo

ssh -L 33389:localhost:33389 foo ssh -t -L 33389:rdp:3389 bar
Run Code Online (Sandbox Code Playgroud)

这似乎完成了工作。

但是,当然,这已经足够了,而且能够将所有这些放入配置文件中并ssh bar在本地机器上简单地输入会更简洁。

随着 RemoteCommand在OpenSSH的7.6推出,这似乎是相当简单:

Host bar
    HostName foo
    RemoteCommand ssh -L 33389:rdp:3389 -A -p 10022 localhost
    LocalForward 33389 localhost:33389
Run Code Online (Sandbox Code Playgroud)

...这应该大致转化为ssh上面显示的调用。但如前所述,我使用的是较旧的(打包的)OpenSSH 版本,不支持该RemoteCommand节。

这是似乎最接近我想要实现的目标的尝试。

Host bar
    HostName localhost
    Port 10022
    ProxyCommand ssh -L 33389:localhost:33389 -W %h:%p foo
    LocalForward 33389 rdp:3389
Run Code Online (Sandbox Code Playgroud)

这个想法是在本地机器上我将简单地调用ssh bar. 事实上,它的工作原理是我最终出现在 的 shell 提示符下bar,但端口转发根本不起作用。而sudo lsof -i|grep 3389在本地机器上给我:

ssh       15271        accden    6u  IPv6 7933201      0t0  TCP localhost:33389 (LISTEN)
ssh       15271        accden    7u  IPv4 7933202      0t0  TCP localhost:33389 (LISTEN)
Run Code Online (Sandbox Code Playgroud)

在跳转主机上,我看不到任何包含3389.

由于ProxyCommand建立了与 的连接,foo并且我正在LocalForward为与 的连接提供一个bar,我希望这能正常工作。

我究竟做错了什么?


目标是用于ssh bar连接到本地计算机并bar同时使其rdp:3389在本地计算机上可用localhost:33389。调整ssh_config(5)本地机器上的文件foo是允许的。但是,传递远程命令不是有效的答案。

A.B*_*A.B 12

首先,根据您的设置,什么起作用,无论如何需要两个 ssh:

Host foo
    LocalForward 10022:bar:22

Host bar
    Hostname localhost
    Port 10022
    LocalForward 33389 rdp:3389

term1$ ssh foo # or use ssh -f -N -o ExitOnForwardFailure=yes foo for background task
term2$ ssh bar
Run Code Online (Sandbox Code Playgroud)

你真正需要的不是 RemoteCommand 而是 ProxyJump,它真​​正简化了你的配置,目标只有

ssh -L 33389:rdp:3389 -J foo bar
Run Code Online (Sandbox Code Playgroud)

或等效(仅)配置:

Host bar
    ProxyJump foo
    LocalForward 33389 rdp:3389
Run Code Online (Sandbox Code Playgroud)

需要零中间端口。

不幸的是,ProxyJump 仅从 openssh 7.3 开始可用

但它很容易被ProxyCommand-W您之前使用/组合替换

ssh -L 33389:rdp:3389 -o 'ProxyCommand=ssh foo -W %h:%p' bar 
Run Code Online (Sandbox Code Playgroud)

或作为配置文件:

Host bar
    ProxyCommand ssh -W %h:%p foo
    LocalForward 33389 rdp:3389
Run Code Online (Sandbox Code Playgroud)

仍然有两个 ssh 正在运行:隐藏的一个是作为ProxyCommand参数仍然在本地主机上运行的一个,它使用一对管道与主 ssh 进行链接,而不是额外的 tcp 端口。尝试让中间主机参与端口转发是不安全的或者会发生冲突(foo 的其他用户可以访问隧道或使用相同的端口),并且容易出错。如果可能,隧道末端应始终保留在客户端主机上,在那里可以完全控制。中间隧道要么不存在,要么指向下一个 ssh 入口点(-W这里是 的用法)。