翻入墙内 | 反向SSH Tunnel | Reverse SSH Tunnel

      状况 | Case

    因为GFW的关系,越来越多的网友熟练掌握了使用SSH Tunnel“翻墙”的方法——这种方法使我们通过墙外一台主机作为代理中转访问国际互联网。网上关于SSH翻墙的文章已经很多,无须赘述,提及此只为特别感谢郭嘉。
    少数情况下,我们不仅需要翻出墙,可能还需要从墙外翻回来。比如你交友不慎,某个邪恶国家友人强烈要求感受一下国内的网络环境;你如此勤奋以至于希望在家中仍然能够连接到公司网络开工,公司却出于体恤员工的考虑没有提供VPN,此时就需要手段先“翻”到公司的院子里。反向的SSH Tunnel就是这样的手段。

      原理 | Principle

    反向SSH Tunnel原理图

    反向SSH Tunnel原理


    在一般的SSH转发模型中,我们从大中华局域网中的Desktop B去SSH连接外部SSH Server X,将A的Px端口映射到X的SSH Server端口(22)。连接建立后我们就可以在应用中指定127.0.0.1:Px为代理。发往127.0.0.1.Px的请求将通过Tunnel发送到X:22,并根据SSH协议中转发的规定转发到外部网络。(此部分图中未表现)。
    在反向SSH Tunnel中,我们由大中华局域网内Desktop B用SSH连接外部主机Desktop A上的SSH Server,并建立一个反向Tunnel,将A:Port1映射到B:Port2。相比于一般的正向Tunnel,反向Tunnel允许SSH连接的被动方A将Port1上的请求通过Tunnel转发到B:Port2上。而B上应有一个应用监听Port2,对Port2上的请求做适宜的处理。对于一般的网络代理而言,此“应用”即为SSH Server。SSH Server监听22端口,并对来自SSH Tunnel的请求通过本地网络转发,起到代理的作用。

      实例 | Practice

    用到反向SSH Tunnel,是因为之前有这样一个需求:我们有一个开发中的网站,将要在外部Web Server(Host A)上布署测试环境,需要在外部主机上获取代码并持续更新。代码通过公司内部的SVN Server(Host S)进行版本控制,公司外部无法访问。我们不希望在外部主机上通过VPN一类软件登录公司网络,而是在必要的时候由内部网络发起连接。因此我们使用反向SSH Tunnel。
    创建反向SSH Tunnel的过程由内网的桌面(Host B)来完成

    1
    root@B#ssh -NfR {PORT_A}:localhost:{PORT_B} {HOST_A} -l {USER@HOST_A}

    1
    root@desktop#ssh -Nf$ 8080:localhost:9090 www.example.com -l webadmin

    输入密码确认后,一个从desktop:8080到www.example.com:9090的反向Tunnel就建好了。在Host A上用

    1
    netstat -ntl | grep 127

    将看到9090端口已经在监听。此后发往www.example.com:9090的请求将被通过Tunnel转送到desktop:8080。
    接下来我们对转发到Host B的8080端口上的请求做处理。在本例中,我们使用Apache Server的Proxy Module来转发请求。为此,首先要确认Apache有安装好mod_proxy和mod_http_proxy。然后,在Apache中添加虚拟主机,配置如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    NameVirtualHost *:8080
    Listen 8080
    # ...
    <VirtualHost *:8080>
        ServerName svn.company-domain.com

        ProxyPass / http://svn.company-domain.com/
        ProxyPassReverse / http://svn.company-domain.com/
        <Proxy *>
            Order deny,allow
            Allow from all
        </Proxy>
        <Directory />
            Order allow,deny
            Allow from all
        </Directory>
    </VirtualHost>

    此配置将在8080端口上建立虚拟主机,并将发往此主机的所有请求转发到http://svn.company-domain.com/。
    这样,一个完整的Reverse SSH Tunnel就建好了。在SSH Tunnel连通时,我们可以使用svn co http://172.0.0.1:9090/trunk/myproject/…/在Host A上下载源码。这个请求首先通过Tunnel进入公司网络,被转发到desktop:8080。然后,再被Apache根据mod_proxy的设置转发到svn.company-domina.com。SVN Server的响应也会按照原路逐级转发回到外部主机Host A。当然,我们也可以再做一些锦上添花的工作比如修改Host A上的本地DNS,将svn.company-domain.com解析到127.0.0.1。
    当必要的任务完成后,只要在Host B上断开SSH连接,外部主机Host A将没有办法访问内部网络。

      更多 | More

    以上只是实现了一个基本的反向SSH Tunnel实例,在此基础上我们还可以做很多,比如最重要的安全策略。我们可以在Host A(www.example.com)上限制对9090(PORT_A)的访问,在Host B上对SSH Server和Apache Proxy做相应的权限,日志等设置。
    另外,虽然从安全模型上说,这种由内部网络主动发起并且可控的连接是可以信任的,但是此办法实质是在公司防火墙上开了个后门。所以在使用前还是要看看公司安全规定有否相关约束。
    关于SSH用法还有无数的内容,部分可参考下面的资源。

      资源 | Resource

    Secure Shell
    Setting up a reverse SSH tunnel
    深入讲解SSH协议的转发概念
    反向建立 SSH Tunnel、免 VPN 連回公司
    上班族ssh tunnel求生手冊
    SSH Tunnel扫盲

    This entry was written by Wang Xiaoxing , posted on Monday September 06 2010at 04:09 pm , filed under Linux, 网络 | Network and tagged , , , , , , , , , , . Bookmark the permalink . Post a comment below or leave a trackback: Trackback URL.

    8 Responses to “翻入墙内 | 反向SSH Tunnel | Reverse SSH Tunnel”

    Leave a Reply

    XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>