SSH 端口转发功能简介和应用示例

SSH (Secure Shell) 是 Linux 发行版用户通过网络访问主机 Shell 命令行界面的常用协议,大多数 Linux 发行版已经预装 OpenSSH 服务端,在一些轻量 Linux 应用场景中则可使用 Dropbear 代替。除了能用于访问 Shell 命令行界面以外,SSH 还具备端口转发和 Proxy 的功能。

在一些应用场景下,目标主机与用户的计算机之间依靠复杂的计算机网络建立连接,两者或两者之间可能有特殊的防火墙系统,或者用户需要临时与目标主机建立某种网络连接时,SSH 协议的这个功能就为用户提供了易于配置的临时端口转发以及 Proxy 解决方案。用户只要能访问目标主机的 SSH,且其服务端支启用了 SSH 这些功能的支持,用户就可以仅使用一个 SSH 端口访问位于目标主机或其所在网络中的各类网络资源。

本文在地平线旭日 X3 制造商提供的 Ubuntu 操作系统上完成实验,所有未提及的配置和操作均为操作系统默认。

SSH 的本地端口转发

在使用 ssh 命令与目标主机建立连接时,用户常使用该形式的命令:

ssh [username@]host -p port

若用户能够使用该命令访问目标主机的 Shell 命令行,则用户可追加以下命令行参数实现端口转发:

-L [listenaddr:]listenport:targethost:targetport

其中 targethost 表示用户想要借助目标主机 host 访问的网络主机,targetport 表示该网络主机上的哪个端口将被转发, listenport 表示用户希望被转发的端口映射到其计算机上的哪个端口,listenaddr 表示用户希望来自哪个网络地址(段)的主机可访问本机上映射的被转发端口,若不提供此值,其默认为 127.0.0.1 (仅本机可访问)。例如,本文作者欲通过开发板的 SSH 服务端访问该开发板的 VNC 服务端(TCP 协议,监听 5900 端口)映射到本人的计算机的 5901 端口上以便 VNC 客户端访问,假定开发板的 IP 地址为 192.168.1.101,则需要用以下命令建立端口转发:

ssh sunrise@192.168.1.101 -L 5901:127.0.0.1:5900

SSH 会话建立后,仍然会提供命令行界面供用户使用,与此同时端口转发已经建立好。当用户使用 VNC 客户端访问 127.0.0.1:5901 时,相当于访问 192.168.1.101:5900;对于开发板而言,访问其 5900 端口的是其自身。这表明即使开发板上 5900 端口监听的网络地址只有 127.0.0.1,用户亦能够访问,即绕过了开发板的防火墙。若用户想要借由该开发板访问 IP 地址为 192.168.1.102 的另一块开发板上的开放端口 80,只需在其计算机上执行如下命令:

ssh sunrise@192.168.1.101 -L 80:192.168.1.102:80

此时,如果用户希望与其计算机在同一局域网下的其它网络设备访问被转发的端口,上述命令应写作:

ssh sunrise@192.168.1.101 -L 0.0.0.0:80:192.168.1.102:80

请注意,命令中新增的 0.0.0.0: 规定了哪个或哪些网络设备能够访问本机上的特定资源,例如在上例中,它规定本机的 80 端口能够被所有其它主机访问,如果写作 192.168.0.0 则只有 IP 地址前两段为 192.168. 的主机可访问,对于熟悉计算机网络的用户而言这并不难理解。需要注意的是,在 Windows 操作系统上首次运行此类命令时,Windows 防火墙会弹出对话框要求用户选择 ssh.exe 可以访问的网络类型,应给予合适的配置以保证端口能被其它网络设备访问,其它具有防火墙的主机类似。

用户应通过结束 SSH 会话的方式结束端口转发,比如键入 exitlogout 之类的命令使目标主机关闭当前 SSH 会话。如果此时被转发的端口上有已经建立的 TCP 连接,端口转发不会立即结束,而是在所有 TCP 连接都断开或用户按下 Ctrl-C 或以其它方式结束该 ssh 进程后结束。

用户可以建立多个 SSH 会话以同时建立多个端口转发。SSH 建立的连接是加密连接,用户的计算机与目标主机间的 SSH 流量受 SSL 加密保护。

SSH 的远程端口转发

当用户的计算机或其网络中的某个主机的服务需要提供给目标主机访问,可以使用 SSH 的远程端口转发功能。该功能与上一节提到的本地端口转发功能相反,其参数为

-R listenport:targethost:targetport

其中 targethosttargetport 表示目标主机要借助用户计算机访问的网络主机以及其端口,listenport 表示在目标主机上选择的监听端口,类似于本地端口转发中对应参数的配置。仍以 IP 地址为 192.168.1.101 的开发板为例,该开发板需要访问用户计算机所在网络中 IP 地址为 172.31.8.14 的 FTP 服务(TCP 协议,监听 21 端口)且其提供 2121 端口用于端口转发,则用户应在其计算机上执行如下命令:

ssh sunrise@192.168.1.101 -R 2121:172.31.8.14:21

在 SSH 会话建立后, 目标主机访问 ftp://127.0.0.1:2121 即等同于访问 ftp://172.31.8.14,且对于 172.31.8.14 而言,访问其 FTP 服务的是用户计算机。如果该 FTP 服务由用户计算机提供,开发板如需访问,只需将命令中的 172.31.8.14 替换为 127.0.0.1 即可。此时若用户在目标主机上执行 ftp 命令,则可以从该 FTP 服务器上取走文件或向 FTP 服务器上放置文件。

建立在 SSH 端口转发上的 VNC 应用实例

本人的开发板经常不在身边,有时需要相隔复杂的网络建立 VNC 连接,而要访问到开发板需要经过多台主机,所有主机均具备 SSH 端口转发。现有此类主机 A、B、C 共 3 台,由于防火墙的限制,本人只能按以下途径访问开发板:

本人电脑 -> 主机 A -> 主机 B -> 主机 C -> 开发板

可以建立多条 SSH 端口转发连续映射以访问开发板的 VNC,路径和所用端口号描述如下:

[5901:]本人电脑:5901 <- 5901:主机 A:5901 <- 5901:主机 B:5901 <- 5901:主机 C:5900 <- 5901:开发板:5900

箭头指示端口转发的映射方向,主机名称左侧是目标端口,右侧是源端口。在命令行中可以按如下方式依次建立 SSH 会话:

user@mycomputer:~ $ ssh hostA -L 5901:127.0.0.1:5901
user@hostA:~ $ ssh hostB -L 5901:127.0.0.1:5901
user@hostB:~ $ ssh hostC -L 5901:127.0.0.1:5901
user@hostC:~ $ ssh sunrise@sunrise -L 5901:127.0.0.1:5900

这种转发方式中,目标主机均为 127.0.0.1,监听地址均保持默认,这最大可能避免了端口暴露导致的安全问题或防火墙问题,使得所有流量仅经过 SSH。使用 TightVNC 团队开发的 VNC 客户端 RemoteRipple访问本机的 5901 端口,输入密码后即可访问远程桌面,如下图。开发板的 VNC 的密码默认为 sunrise,此时 /etc/.vnc/passwd 为空,如果需要另外设置密码可使用 x11vnc 命令在该文件中设定密码,下次连接时生效。

RemoteRipple连接映射到本机的VNC

补充说明

对于本地端口转发而言,所有流量均经过目标主机转发;对于远程端口转发而言,所有流量均经过本机转发。

以任何形式建立端口转发后,被转发的端口都不会被立即访问,而是在有请求时才访问。如果用户指定了不可访问的主机或端口,在 SSH 会话建立后并无异样,但当用户试图在转发的端口上建立连接时,SSH 会话中将出现如下提示或类似提示:

channel 3: open failed: connect failed: Connection refused

该提示代表 targethost 拒绝了提供端口转发的主机对其 targetport 的访问请求,通常是由于该主机设定了对应的防火墙规则。在其它异常情况下,SSH 会话中亦有相应的提示。

SSH 的端口转发功能通常被临时使用,但经实际测试,其转发效果与其它端口转发方式相比在常规使用场景下并不大,且如果用户计算机与某一网络主机不能建立稳定的网络连接,但目标主机能够做到,用户在其计算机上通过 SSH 与目标主机建立的端口转发可使得连接更稳定。总而言之,SSH 的端口转发功能提供了便捷、可靠、安全的端口转发方案,能够满足绝大多数应用场景的要求。