案例1

情形

本机 A 到远程服务器 B 的 ssh 连接经由公网,存在着时有受到干扰、不稳定等问题,但是本机可访问一个 socks5 代理服务,记做 C.

现在我们希望 A 到 B 的 ssh 流量先经过 C 并且由 C 转发到 B.

example-1.png

解决方案

ssh 提供了一个选项(option, -o)叫做 ProxyCommand, 现在我们假设 C 提供的 socks5 服务能够通过本机 A 的 127.0.0.1:7890 来访问,那么我们可以使用以下命令来实现上述需求:


ssh -o 'ProxyCommand /opt/homebrew/bin/ncat --proxy 127.0.0.1:7890 --proxy-type socks5 %h %p' \\
  loginUserName@remote-host \\
  -p portNumber \\
  -i /path/to/privateKey

如果去掉选项 -o 还有 -o 后面接的那一个字符串,那么上列命令就和正常的 ssh 连接命令一样,所以我们主要来看 -o ProxyCommand 是什么意思:

ncat 是一个连接命令,—-proxy 127.0.0.1:7890 表示 ncat 将通过 127.0.0.1:7890 这个 socks5 代理服务来发起连接(而不是直接连接),—-proxy-type socks5 声明 127.0.0.1:7890 提供的代理服务的类型(是 socks5),%h %p 将交由 ssh 并且会被分别替换为 ssh 想要连接到的主机名和端口号,这里就是 remote-host 和 portNumber.

这条命令:

/opt/homebrew/bin/ncat --proxy 127.0.0.1:7890 --proxy-type socks5 %h %p

替换了 %h 和 %p 之后执行时就可作为一个管道,ssh 将这个管道视作一个 tcp 连接,然后这个管道的出口实际上就是 127.0.0.1:7890 这个 socks5 服务的出口,ssh 流量将从这里被转发至 remote-host.

另外,我们还可以通过编辑 ~/.ssh/config 文件,加入下列内容:

Host remote-host-mnemonic
    Hostname remote-host-name
    User root
    Port portNumber
    IdentityFile /path/to/privateKey
    ProxyCommand /opt/homebrew/bin/ncat --proxy 127.0.0.1:7890 --proxy-type socks5 %h %p

来方便后续这样的操作:只需执行 ssh remote-host-mnemonic 就可得到和刚才那条长长的 ssh 命令一样的效果。

案例2

情形

公司内网机器不能直接登录,只能通过一台公网跳板机登录。

假设这台跳板机器叫做 A, 想要登录上的内网机器叫做 B, 那么我们一般可能会这样: