SSH: Tunneling

1st September 2021 at 3:27pm

SSH tunneling 有两种功能:

  • Local port forwarding,一般讲 port forwarding 是指这个
  • Remote port forwarding,也称 reverse tunnel

它们被用来 bypass 某些防火墙策略。简单来讲:

Local port forwarding:

  • 你想访问 B server 的某个端口,但是被防火墙挡住了
  • 你有通过 SSH 访问 A server 的能力,同时 A server 可以访问 B server 的这个端口
  • 你通过 SSH client,在本地 bind 某个端口,使得向这个端口的请求,通过 SSH 转发到 A server,再由 A server 的 SSH server 转发到 B server
  • 此时你可以访问 B server 了

Remote port forwarding 则是反过来:

  • 外部想访问你的本地某端口服务,但是被防火墙挡住了
  • 你跟外部之间,共同可以访问 A server
  • 你通过 SSH 访问 A server,要求 A 的 SSH server bind 某个端口,使得到这个端口的请求,通过 SSH 传到你本地上、想被外部访问的端口
  • 此时外部就可以访问你本地的端口了

这篇 文章 讲得很清晰直观。看它。

同时注意,SSH 不仅可以 tunneling 端口,也可以是 sock 文件。

通过 XShell 配置

XShell 提供了图形化配置的能力:

其中源主机是指你的本地主机,侦听端口是指 tunnel 建立后会 bind 的本地端口,可以通过这个端口来访问远端主机的服务。

目标主机是指你的远端主机去访问服务时用的名称。如果你的 MySQL 服务 IP 是 1.2.3.4,那么目标主机就写这个 IP。目标端口即服务的端口,比如 MySQL 的 3306。

配置好后,你需要重开 / 重连你的 XShell session,这个 tunnel 才会建立起来。

命令行

假如你的远端机器是 5.6.7.8,远端机器可访问的 MySQL 服务地址是 1.2.3.4。如果你想通过访问本机的 9000 端口,来访问到远端的这个 MySQL 服务,那需要在你的本地机器上运行:

ssh -CNL 9000:1.2.3.4:3306 onlyice@5.6.7.8
  • L 表示这是 port forwarding
  • C 表示压缩请求
  • N 表示不登陆到 server 上,仅打开 tunnel;不指定 N 时会给你一个 server 的命令提示符,跟正常 SSH 登陆 server 一样

OpenSSH 配置文件

~/.ssh/config 中可以定义:

Host myvm
    User onlyice
    HostName 1.1.1.1
    IdentityFile ~/.ssh/id_rsa
    LocalForward 8300 example.com:3000

配置好后,你运行 ssh myvm 时,会自动打通隧道;访问本机 8300 端口时,会通过 myvm 访问远端的 example.com:3000。

你也可以通过 VSCode 的 Remote SSH 功能打开 myvm;VSCode 也会把隧道打通。