SSH远程端口转发原理与内网穿透

基本概念

所谓远程端口转发,其实说白了就是基于这样一种思想:既然没有公网IP地址的客户端(比如我的笔记本)可以“看”到具有公网IP地址的服务器(比如我的VPS服务器)的一切信息,即能够与它的任意端口通信;那么反过来,通过这条建立好的连接,服务器也应该能够“看”到客户端,能够与客户端的任意端口通信。

这是一个非常有用的功能,因为一旦有了它,也就意味着我们可以通过公网上面一台服务器作为中转,来访问任意一台虽然不具有独立IP但是能够连接到公网服务器上的电脑,这也就是所谓的“内网穿透”。实际上,TeamViewer等远程控制软件利用的就是这个原理。

对于公网上的服务器而言,它只需要将访问自身某个端口的请求(假如是80端口),通过建立好的连接,直接转发到内网机器的80端口上,再把返回的数据发送给那个访问者即可。这样,在外网的访问者看来,自己访问的完全就是内网那台机器的80端口。

实战操作

事实上,SSH协议软件的实现中,正是提供了对这样一个重要功能的支持。我们在客户端电脑(也就是位于内网的机器)上执行这条命令建立连接:

ssh -N -f -R 6801:127.0.0.1:6800 user@server_ip_address

就可以实现将客户端自身的6800端口转发到外部服务器的6801端口上;而外部访问者则能通过公网机器的6801端口,连接到内部机器127.0.0.1的6800端口上面。

为什么这里还要指定内网机器的IP地址127.0.0.1呢?需要把端口转发到公网服务器上面的不应该就只有客户端自己吗?其实这个设计是为了提升命令的通用性,也就是说需要转发的并不一定就是客户端自己的端口。

我们考虑下图中这样一个使用场景:一系列办公机器组成局域网,其中只有一台机器能够访问外网,另一台则被防火墙挡住无法访问。现在我们需要从外网访问其中一台不能够访问外网的机器B的80端口,如标有黄色问号的蓝色箭头所示。

网络结构示意图

从信息流动的角度来讲,这个需求应当是可以实现的:因为外网服务器和内网中能上网的那台机器可以交换数据,而内网中能上网和不能上网的机器也可以交换数据,如图中两个绿色的箭头所示。因此,在实现SSH端口转发的时候,我们就要指定一个IP地址,来表明要转发的是客户端自己的端口,还是与客户端处于同一内网的其他机器的端口。

此外,对于上图这样一个稍微复杂的使用场景,整个转发过程涉及到了三台机器:公网中的服务器、内网中能访问外网的机器A与不能访问外网的机器B;并且只在公网服务器上面占用新的端口。因此,在公网服务器上面需要有开启这个端口的权限,但在内网机器A、B上面不需要任何额外权限。因为对于机器A而言,它只是建立了一个SSH连接而已,只要能访问机器B的对应端口即可;而对于机器B而言,它的端口开放着,任何内网的机器都可以访问,所以同样不需要什么额外设置。

comments powered by Disqus
Published:
2015-02-20
分类:
Tag: