By Bill Ebbesen - Transferred from en.wikipedia, CC BY 3.0, https://commons.wikimedia.org/w/index.php?curid=11430127

在Windows电脑之间搭建SSH反向隧道进行内网穿透

不少人肯定和笔者一样都有从外网访问内网服务器的需求,比如从外网访问学校的内网或者是企业的内网,这样我们在离开工作场所的地方依然可以方便存取上面的数据。但是内网服务器往往只具有一个内网IP,而且作为普通用户的我们往往没有权限在NAT网关上配置端口转发,这就使得访问内网成为一项难题。

为了解决这个问题,有些学校和企业会提供VPN给学生和员工来使用,但是据我所知这样做的学校和企业并不是绝大多数,所以很多时候还是需要依靠我们自己来寻找访问内网服务器的方法。

去年(2015年)下半年微软放出了第一版OpenSSH for Windows的源代码,并且表示未来会在PowerShell中支持SSH,近期有消息说这个事情马上就要成为现实了。SSH除了作为远程管理的重要手段之外,还有一个非常有用的功能就是搭建隧道,尤其是搭建反向隧道(reverse tunnel)。网上关于在安装有Linux操作系统的计算机之间搭建反向隧道的文章数不胜数,但是关于在Windows上搭建反向隧道的文章寥寥无几,本文会从反向隧道的搭建以及相关配套软件的选择及应用等方面对通过反向隧道访问内网的方法进行详细阐述。

解决方案概述

首先,我们有一台可以完全控制的位于NAT网关之内的只有内网IP的电脑(以下简称“内网电脑”),以及一台可以完全控制的具有外网IP的电脑(以下简称“外网电脑”),内网电脑可以通过互联网访问到外网电脑。两台电脑均安装Windows,我们首先在外网电脑上部署SSH服务,然后在内网电脑上通过SSH建立反向隧道,最后在内网电脑上架设一个代理服务器,从而使得外网电脑获得对内网电脑所在内网的访问权限。

在外网电脑上部署SSH

目前,Windows并没有原生的SSH服务供大家使用,但是我们可以使用Win32-OpenSSH作为代替。根据项目Wiki中的部署指南,部署Win32-OpenSSH的步骤如下:
1.下载最新版的Win32-OpenSSH

2.将压缩包内的文件解压到“C:\Win32-OpenSSH”。

3.以管理员身份启动cmd(命令提示符),并切换至Win32-OpenSSH的安装目录。

cd "C:\Win32-OpenSSH"

4.生成SSH host keys。

ssh-keygen -A

5.在防火墙规则中放行SSH服务所用端口(TCP 22)。

netsh advfirewall firewall add rule name="SSH Port" dir=in action=allow protocol=TCP localport=22

6.安装为NT服务。

sshd install

7.启动SSH服务。

net start sshd

8.将服务设置为自动启动。

sc config sshd start= auto

至此,OpenSSH服务在外网电脑上部署完成。

在内网电脑上开启反向隧道

我们需要一个支持隧道功能的SSH客户端来在内网电脑上开启反向隧道,这里我们用putty做例子。
下载并运行putty之后,在Session里填入服务器的地址(Host Name or IP address)和端口(Port),连接类型(Connection type)选择“SSH”。填完之后先不急着连接,还需要在Connection->SSH->Tunnels里面配置隧道的相关参数,在这里我们以下图作为例子进行讲解。
putty-tunnel-settings
Port fowarding下面有2个选项:
“Local ports accept connections from other hosts”是指正向隧道映射出来的本地端口可以被除内网电脑之外的其他计算机访问(即将socket绑定至0.0.0.0而不是127.0.0.1)。
“Remote ports do the same (SSH-2 only)”是指反向隧道的远程端口(即外网电脑上映射出来的端口)可以被除外网电脑之外的其他计算机访问,如果需要将外网电脑作为一个连接内网电脑的代理服务器的话,可以勾选这个选项。注意这个特性只在SSH-2中有效,而且不是所有的支持SSH-2的服务器都支持这个特性,在Win32-OpenSSH中需要把“GatewayPorts”设置为“yes”才可以让这个功能生效。

Forwarded ports下面就是已经添加好的隧道列表,点击“Remove”可以删除。

Add new forwarded port下面就是我们要填入的新隧道的信息:
“Source port”即源端口,在反向隧道当中,这个端口是在外网电脑上开启的端口,我们这里设置为8488。
“Destination”即转发的目的端口,在反向隧道当中,我们将它设置为“localhost:8388”,即将外网电脑上的8488端口上的数据全部转发到内网电脑的8388端口上。
接下来的一行选项是隧道模式,这里选择“Remote”,即在远程计算机上完成映射,也就是反向隧道。
最后一行是IP协议版本,选择“Auto”即可。

设置完成后点击“Open”即可启动隧道。

在内网电脑上部署代理服务器

很多人都知道SSH的动态隧道模式(ssh -d)可以当作socks代理来用,但是这个模式和反向隧道模式是两个独立的模式,也就是说不能在反向隧道当中应用动态隧道,这样我们就需要一个单独的代理服务器工具来实现代理功能。

笔者在解决本文开头所述的问题时所采用的代理服务器是目前很火的shadowsocks,主要是因为其部署比较简便,而且客户端的种类非常丰富,应用起来比较灵活。关于部署和应用shadowsocks的相关内容,网上已有很多,这里不再赘述。

当然,也可以在内网电脑上开启一个SSH服务,然后在外网电脑上通过之前建立起的反向隧道访问这个内网的SSH服务,再用动态隧道来实现socks代理。

在内网电脑上部署代理服务器时,其开放的端口应和上面的隧道端口一致,在本文所述的例子当中,内网电脑上的代理服务器端口应该为TCP 8388。

在外网电脑上,由于反向隧道的存在,内网电脑上开启的代理服务器已经被映射到了127.0.0.1:8488上。如果采用的是shadowsocks,则将shadowsocks客户端中的代理服务器地址直接设置为“127.0.0.1:8488”即可通过内网电脑上的代理服务器访问内网。如果采用的是普通的socks代理或http代理,则将浏览器的代理服务器设置为“127.0.0.1:8488”即可访问内网电脑所在的内网。

 

封面图片:
Picture from the tunnel between Rigshospitalet (National Hospital) in Copenhagen and Amagerværket (Amager Powerplant) in Amager. The tunnel transfers heated water and steam for the city.
By Bill Ebbesen – Transferred from en.wikipedia, CC BY 3.0, https://commons.wikimedia.org/w/index.php?curid=11430127

CC BY-NC 4.0 本作品使用基于以下许可授权:Creative Commons Attribution-NonCommercial 4.0 International License.

《在Windows电脑之间搭建SSH反向隧道进行内网穿透》上有2条评论

  1. 然而在不稳定的网络情况下,ssh隧道经常容易断开,用autossh之类也只能是断开重连,这是ssh协议本身的问题吗,还有什么好办法吗?

    1. 目前我发现的引起SSH隧道断开的原因主要有2个:
      第一个是网络本身的问题,比如丢包、掉线、IP变化等等。这种基本上没法处理。
      第二个就是有些网关,在发现某个连接很久没有数据通过时便会把这个连接关掉。这个原因引起的断开就比较好解决,定时发送一定的数据,保持总是有数据收发就可以了。

发表评论

电子邮件地址不会被公开。 必填项已用*标注