网络的使用,离不开安全措施的部署。在网络自身当中,也有相关规定的安全协议。今天我们介绍的就是其中的SSH协议。那么如何在具体的设置中体现出SSH协议的作用呢?我们今天就来介绍一下相关的内容。那么通过本文的介绍,读者可以从中了解到如何应用SSH端口转发机制来解决日常工作/生活中的一些问题。学会在非安全环境下使用端口转发来加密网络应用,保护个人隐私以及重要商业信息。同时也能够用此技术解决工作中一些常见问题,例如解决防火墙及网络应用本身带来的一些限制。
第一部分 概述
当你在咖啡馆享受免费 WiFi 的时候,有没有想到可能有人正在窃取你的密码及隐私信息?当你发现实验室的防火墙阻止了你的网络应用端口,是不是有苦难言?来看看SSH的端口转发功能能给我们带来什么好处吧!
端口转发概述
让我们先来了解一下端口转发的概念吧。我们知道,SSH协议会自动加密和解密所有SSH客户端与服务端之间的网络数据。但是,SSH 还同时提供了一个非常有用的功能,这就是端口转发。它能够将其他TCP端口的网络数据通过SSH链接来转发,并且自动提供了相应的加密及解密服务。这一过程有时也被叫做“隧道"(tunneling),这是因为SSH为其他TCP链接提供了一个安全的通道来进行传输而得名。例如,Telnet,SMTP,LDAP 这些TCP应用均能够从中得益,避免了用户名,密码以及隐私信息的明文传输。而与此同时,如果您工作环境中的防火墙限制了一些网络端口的使用,但是允许SSH的连接,那么也是能够通过将TCP端口转发来使用SSH进行通讯。总的来说SSH端口转发能够提供两大功能:
加密SSH Client 端至SSH Server端之间的通讯数据。突破防火墙的限制完成一些之前无法建立的TCP连接。
图 1.SSH端口转发
如上图所示,使用了端口转发之后,TCP 端口 A 与 B 之间现在并不直接通讯,而是转发到了SSH协议客户端及服务端来通讯,从而自动实现了数据加密并同时绕过了防火墙的限制。#p#
第二部分 本地转发与远程转发
本地转发实例分析
我们先来看第一个例子,在实验室里有一台 LDAP 服务器(Ldap Server Host),但是限制了只有本机上部署的应用才能直接连接此 LDAP服务器。如果我们由于调试或者测试的需要想临时从远程机器(LdapClientHost)直接连接到这个 LDAP 服务器 , 有什么方法能够实现呢?
答案无疑是本地端口转发了,它的命令格式是:
- ssh -L <local port>:<remote host>:<remote port> <SSH hostname>
在Ldap Client Host上执行如下命令即可建立一个SSH协议的本地端口转发,例如:
- $SSH-L 7001:localhost:389 Ldap Server Host
图 2. 本地端口转发
这里需要注意的是本例中我们选择了 7001 端口作为本地的监听端口,在选择端口号时要注意非管理员帐号是无权绑定 1-1023 端口的,所以一般是选用一个 1024-65535 之间的并且尚未使用的端口号即可。
然后我们可以将远程机器(LdapClientHost)上的应用直接配置到本机的 7001 端口上(而不是 LDAP 服务器的 389 端口上)。之后的数据流将会是下面这个样子:
我们在Ldap Client Host上的应用将数据发送到本机的 7001 端口上,而本机的SSH Client 会将 7001 端口收到的数据加密并转发到 LdapServertHost 的SSH Server 上。SSH Server 会解密收到的数据并将之转发到监听的 LDAP 389 端口上,最后再将从 LDAP 返回的数据原路返回以完成整个流程。我们可以看到,这整个流程应用并没有直接连接 LDAP 服务器,而是连接到了本地的一个监听端口,但是SSH端口转发完成了剩下的所有事情,加密,转发,解密,通讯。
这里有几个地方需要注意:
SSH协议端口转发是通过SSH连接建立起来的,我们必须保持这个SSH连接以使端口转发保持生效。一旦关闭了此连接,相应的端口转发也会随之关闭。我们只能在建立SSH连接的同时创建端口转发,而不能给一个已经存在的SSH连接增加端口转发。
你可能会疑惑上面命令中的 <remote host> 为什么用 localhost,它指向的是哪台机器呢?在本例中,它指向 LdapServertHost 。我们为什么用 localhost 而不是 IP 地址或者主机名呢?其实这个取决于我们之前是如何限制 LDAP 只有本机才能访问。如果只允许 lookback 接口访问的话,那么自然就只有 localhost 或者 IP 为 127.0.0.1 才能访问了,而不能用真实 IP 或者主机名。
命令中的 <remote host> 和 <SSH hostname> 必须是同一台机器么?其实是不一定的,它们可以是两台不同的机器。我们在后面的例子里会详细阐述这点。好了,我们已经在Ldap Client Host建立了端口转发,那么这个端口转发可以被其他机器使用么?比如能否新增加一台 LdapClientHost2 来直接连接Ldap Client Host的 7001 端口?答案是不行的,在主流SSH实现中,本地端口转发绑定的是 lookback 接口,这意味着只有 localhost 或者 127.0.0.1 才能使用本机的端口转发 , 其他机器发起的连接只会得到“ connection refused. "。好在SSH同时提供了 GatewayPorts 关键字,我们可以通过指定它与其他机器共享这个本地端口转发。
- ssh -g -L <local port>:<remote host>:<remote port> <SSH hostname>
远程转发实例分析
我们来看第二个例子,这次假设由于网络或防火墙的原因我们不能用SSH协议直接从Ldap Client Host连接到 LDAP 服务器(LdapServertHost),但是反向连接却是被允许的。那此时我们的选择自然就是远程端口转发了。
它的命令格式是:
- ssh -R <local port>:<remote host>:<remote port> <SSH hostname>
例如在 LDAP 服务器(LdapServertHost)端执行如下命令:
- $SSH-R 7001:localhost:389Ldap Client Host
图 3. 远程端口转发
和本地端口转发相比,这次的图里,SSH Server 和SSH Client 的位置对调了一下,但是数据流依然是一样的。我们在Ldap Client Host上的应用将数据发送到本机的 7001 端口上,而本机的SSH Server 会将 7001 端口收到的数据加密并转发到 LdapServertHost 的SSH Client 上。SSH Client 会解密收到的数据并将之转发到监听的 LDAP 389 端口上,最后再将从 LDAP 返回的数据原路返回以完成整个流程。
看到这里,你是不是会有点糊涂了么?为什么叫本地转发,而有时又叫远程转发?这两者有什么区别?
本地转发与远程转发的对比与分析
不错,SSH Server,SSH Client,Ldap Servert Host,Ldap Client Host,本地转发,远程转发,这么多的名词的确容易让人糊涂。让我们来分析一下其中的结构吧。首先,SSH 端口转发自然需要SSH连接,而SSH协议连接是有方向的,从SSH Client 到SSH Server 。而我们的应用也是有方向的,比如需要连接 LDAP Server 时,LDAP Server 自然就是 Server 端,我们应用连接的方向也是从应用的 Client 端连接到应用的 Server 端。如果这两个连接的方向一致,那我们就说它是本地转发。而如果两个方向不一致,我们就说它是远程转发。我们可以回忆上面的两个例子来做个对照。
本地转发时:
LdapClientHost 同时是应用的客户端,也是SSH Client,这两个连接都从它指向 LdapServertHost(既是 LDAP 服务端,也是SSH Server)。
远程转发时:
LdapClientHost 是应用的客户端,但却是SSH Server ;而 LdapServertHost 是 LDAP 的服务端,但却是SSH Client 。这样两个连接的方向刚好相反。
另一个方便记忆的方法是,Server 端的端口都是预定义的固定端口(SSH Server 的端口 22,LDAP 的端口 389),而 Client 端的端口都是动态可供我们选择的端口(如上述例子中选用的 7001 端口)。如果 Server 端的两个端口都在同一台机器,Client 端的两个端口都在另一台机器上,那么这就是本地连接;如果这四个端口交叉分布在两个机器上,每台机器各有一个 Server 端端口,一个 Client 端端口,那就是远程连接。
弄清楚了两者的区别之后,再来看看两者的相同之处。如果你所在的环境下,既允许Ldap Client Host发起SSH连接到 Ldap Server Host,也允许 Ldap Server Host 发起SSH协议连接到 Ldap Client Host 。那么这时我们选择本地转发或远程转发都是可以的,能完成一样的功能。
接着让我们来看个进阶版的端口转发。我们之前涉及到的各种连接/转发都只涉及到了两台机器,还记得我们在本地转发中提到的一个问题么?本地转发命令中的 <remote host> 和 <SSH hostname> 可以是不同的机器么?
- ssh -L <local port>:<remote host>:<remote port> <SSH hostname>
答案是可以的!让我们来看一个涉及到四台机器 (A,B,C,D) 的例子。
图 4. 多主机转发应用
在SSH Client(C) 执行下列命令来建立SSH协议连接以及端口转发:
- $SSH-g -L 7001:<B>:389 <D>
然后在我们的应用客户端(A)上配置连接机器(C )的 7001 端口即可。注意我们在命令中指定了“ -g "参数以保证机器(A)能够使用机器(C)建立的本地端口转发。而另一个值得注意的地方是,在上述连接中,(A)<-> (C) 以及 (B)<->(D) 之间的连接并不是安全连接,它们之间没有经过SSH的加密及解密。如果他们之间的网络并不是值得信赖的网络连接,我们就需要谨慎使用这种连接方式了。#p#
第三部分 其他类型的转发
动态转发实例分析
恩,动态转发,听上去很酷。当你看到这里时,有没有想过我们已经讨论过了本地转发,远程转发,但是前提都是要求有一个固定的应用服务端的端口号,例如前面例子中的 LDAP 服务端的 389 端口。那如果没有这个端口号怎么办?等等,什么样的应用会没有这个端口号呢?嗯,比如说用浏览器进行 Web 浏览,比如说 MSN 等等。
当我们在一个不安全的 WiFi 环境下上网,用SSH协议动态转发来保护我们的网页浏览及 MSN 信息无疑是十分必要的。让我们先来看一下动态转发的命令格式:
- $SSH-D <local port> <SSH Server>
例如:
- $SSH-D 7001 <SSH Server>
图 5. 动态端口转发
似乎很简单,我们依然选择了 7001 作为本地的端口号,其实在这里SSH是创建了一个 SOCKS 代理服务。来看看帮助文档中对 -D 参数的描述:
-D port This works by allocating a socket to listen to port on the local side, and whenever a connection is made to this port, the con- nection is forwarded over the secure channel, and the applica- tion protocol is then used to determine where to connect to from the remote machine. Currently the SOCKS4 and SOCKS5 protocols are supported, andSSHwill act as a SOCKS server. Only root can forward privileged ports. Dynamic port forwardings can also be specified in the configuration file.
之后的使用就简单了,我们可以直接使用 localhost:7001 来作为正常的 SOCKS 代理来使用,直接在浏览器或 MSN 上设置即可。在SSH Client 端无法访问的网站现在也都可以正常浏览。而这里需要值得注意的是,此时SSH协议所包护的范围只包括从浏览器端(SSH Client 端)到SSH Server 端的连接,并不包含从SSH Server 端 到目标网站的连接。如果后半截连接的安全不能得到充分的保证的话,这种方式仍不是合适的解决方案。
X协议转发实例分析
好了,让我们来看最后一个例子-X协议转发。
我们日常工作当中,可能会经常会远程登录到 Linux/Unix/Solaris/HP 等机器上去做一些开发或者维护,也经常需要以 GUI 方式运行一些程序,比如要求图形化界面来安装 DB2/WebSphere 等等。这时候通常有两种选择来实现:VNC 或者X窗口,让我们来看看后者。
使用X窗口通常需要分别安装:X Client 和XServer 。在本例中我们的XClient 就是所访问的远程 Linux/Unix/Solaris/HP,而我们的XServer 则是发起访问的本地机器(例如你面前正在使用的笔记本或台式机)。把XClient 端的X窗口显示在XServer 端需要先行在XClient 端指定XServer 的位置,命令格式如下:
- export DISPLAY=<X Server IP>:<display #>.<virtual #>
例如:
- export DISPLAY=myDesktop:1.0
然后直接运行X应用即可,X 窗口就会自动在我们的本地端打开。
一切运行正常,但是,这时候 IT 部门突然在远程 Linux/Unix/Solaris/HP 前面加了一道防火墙。非常不幸的是,X协议并不在允许通过的列表之内。怎么办?只能使用 VNC 了么?不,其实只要使用了SSH协议端口转发即可通过,同时也对X通讯数据做了加密,真是一举两得。(当然,使用此方法前最好先咨询相关 IT 部门是否符合相应的安全条例,以免造成违规操作。)
建立命令也很简单,直接从本地机器(X Server 端)发起一个如下的SSH连接即可:
- $SSH-X <SSH Server>
图 6. X转发
建立连接之后就可以直接运行远程的X应用。注意建立X转发之后会自动设置 DISPLAY 环境变量,通常会被设置成localhost:10.0,我们无需也不应该在连接之后再进行修改此环境变量。
一个比较常见的场景是,我们的本地机器是 Windows 操作系统,这时可以选择开源的 XMing 来作为我们的 XServer,而SSH Client 则可以任意选择了,例如 PuTTY,Cygwin 均可以配置 访问SSH的同时建立X转发。#p#
第四部分 总结
至此,我们已经完成了本地端口转发,远程端口转发,动态端口转发以及X转发的介绍。回顾起来,总的思路是通过将TCP连接转发到SSH协议通道上以解决数据加密以及突破防火墙的种种限制。对一些已知端口号的应用,例如 Telnet/LDAP/SMTP,我们可以使用本地端口转发或者远程端口转发来达到目的。动态端口转发则可以实现 SOCKS 代理从而加密以及突破防火墙对 Web 浏览的限制。对于X应用,无疑是X转发最为适用了。虽然每一部分我们都只是简单的介绍了一下,但如果能灵活应用这些技巧,相信对我们的日常生活/工作也是会有所帮助的。
参考资料
《SSH权威指南》(O'Reilly 图书)详细介绍了SSH相关的更多技术内幕及相关技巧。在developerWorks中国网站Linux专区中学习更多 Linux 方面的知识。
作者简介
申毅,IBM中国软件开发中心 WebSphere Portal 部门软件工程师。目前从事于 WebSphere Portal z/OS 升级包的开发工作。同时较为关注 Linux/Mac 平台上的相关技术。
邵华,IBM中国软件开发中心 WebSphere Portal 部门软件工程师。目前从事与 WebSphere Portal FVT 的相关工作,对 Linux及Web相关技术较为关注。