案例1
在SoftLayer里的一台机器 10.121.196.144 需要访问github,但是无法直接访问。
网络连通性如下:
github <== SVL SDS server ==> SL jumper ==> 10.121.196.144
由于SDS server能连通github,所以可以借助SDS server和SL jumper,从而让 10.121.196.144 能够连通github。
具体实现如下:
在SL jumper上:
ssh -qTfnN -R 60000:localhost:60000 idcuser@10.121.196.144
这条命令表示,建立一个ssh远程转发,把发到 10.121.196.144 的60000端口的请求,转发到localhost的60000端口。
注意,这里的localhost,实际上指的是SL jumper。
注:远程转发(-R)与本地转发(-L)的区别:
ssh连接分为client和server,建立的tunnel也分client和server,如果希望二者方向是一致的,就用Local;如果相反,就用remote。
本例中,ssh client是SL jumper,ssh server是10.121.196.144,而想要建立的tunnel,是反过来的,从10.121.196.144到SL jumper,所以用remote。
如果想用local,则应以10.121.196.144为ssh client。但是,从10.121.196.144无法ssh到SL jumper,所以只能把SL jumper作为ssh client,并用remote。
不管是-L还是-R,后面的<port1> : <host> : <port2>里面:
- port1:都是tunnel client的端口;
- port2:都是目的地的端口;
- host:转发的目的地。如果是localhost,都是指tunnel server本身(因为也可以转发到其它机器上去);
也就是说,这个ssh tunnel,会把tunnel client的指定端口的请求,转发到“host”(可以是tunnel server,也可以是tunnel server能够access的其它机器)的指定端口。
注意,这个tunnel里指定了tunnel client的端口,但并没有指定tunnel server的端口。
接下来,因为SL jumper无法ssh到SDS server,所以同理,要从SDS server上建立一个反向tunnel。
在SDS server上:
ssh -qTfnN -R 60000:github.rtp.raleigh.ibm.com:22 sljump
可见,这是一个remote转发,会把发到SL jumper的60000端口的请求,转发到github的22端口。
注意:这里tunnel server不是localhost(指的是SDS server),而是github。
当然,ssh tunnel只是从SL jumper到SDS server,从后面从SDS server到github,并不是ssh,而是tunnel client本身的请求而定。ssh tunnel只是代理了从tunnel client到tunnel server这一段。
实现效果:
现在,在10.121.196.144上,可以把localhost的60000端口视为github的22端口,即可以通过ssh方式访问了:
[idcuser@cdsmon-wei-01 cdsmon-e2e]$ git remote -v origin ssh://git@localhost:60000/cds-delivery/cdsmon-e2e.git (fetch) origin ssh://git@localhost:60000/cds-delivery/cdsmon-e2e.git (push)
我觉得不管用local还是remote方式,都是实现了一个反向代理。
- 所谓正向代理,proxy代理的是client。client知道自己被代理,client把请求通过proxy发送到server,server只知道proxy不知道client;
- 所谓反向代理,proxy代理的是server。client只知道proxy不知道server,client把请求发给proxy,proxy再转发给server;
对于SSL tunnel,不管用local还是remote方式创建,最终都是实现了从tunnel client访问localhost的某端口时,转发到了指定的server和端口,显然代理的是server。因此,这是一个反向代理。
案例2
有些网站无法直接访问。
既然SDS server可以访问,就可以建立ssh tunnel,实现一个正向代理(这回又变成正向了。。。)。
以我的Mac为例,网络连通性如下:
Mac ==> SDS server ==> 网站
可以利用Mac 到 SDS server 的连通性,建立一个动态转发(-D)。
在Mac上:
ssh -o ExitOnForwardFailure=yes -qTfN -D 8888 kaiding@sdsvm902066.svl.ibm.com
该命令在本地建立了一个SOCKS代理服务,当有请求连接到该端口(本例中是8888)时,就会转发到remote server(本例中是 sdsvm902066.svl.ibm.com )。然后从remote server,那个请求本身再被用起来(比如请求的服务器地址、端口、协议等)。
说白了就是建立了一个正向代理(SOCKS代理)。在浏览器里设置好该代理,就能访问网站了。
比如我的Mac的Chrome浏览器,使用了SwitchyOmega插件,其设置的代理为SOCKS 5,server是127.0.0.1,端口是8888。
Firefox浏览器的代理设置如下图所示:

注:如果希望使用代理服务器的DNS,则需勾选“Proxy DNS when using SOCKS v5”选项。
案例3
想要在Mac上访问http://10.xx.xx.xx的URL。该案例和案例2非常类似,唯一不同是中间多了一层。网络连通性如下:
Mac ==> SDS server ==> sljumper ==> 10.xx.xx.xx
首先,在SDS server上建立一个到SL jumper的动态转发。
ssh -o ExitOnForwardFailure=yes -qTfnN -D 6666 sl
然后,在Mac上建立一个到SDS server的local tunnel。
ssh -o ExitOnForwardFailure=yes -qTfnN -L 6666:localhost:6666 sdsvm902066.svl.ibm.com
最后在浏览器里设置代理为 localhost:6666 即可。
注:本来我想,不需要第2步了,直接在浏览器里面,设置代理为sdsvm902066.svl.ibm.com:6666不就行了吗。
但是这个方法不可行,因为在Mac上SDS server的6666端口nc不通(在SDS server上可以nc通本地的6666端口)。
~ nc -zv sdsvm902066.svl.ibm.com 6666 nc: connectx to sdsvm902066.svl.ibm.com port 6666 (tcp) failed: Connection refused
但这并不是防火墙的问题,因为我在SDS server上用nodejs起一个HTTP server,比如起到3000端口,则在Mac上也能nc通SDS server的3000端口。但是若把ssh tunnel开在3000端口,则在Mac上就nc不通了。
所以,只好用第2步,在本地和SDS server之间建立一个tunnel,然后把代理设置成本地。
注:对这个案例,如果不用浏览器代理,也不用动态转发,也有一个笨办法。假设要访问的URL是http://10.107.28.250:8080/seyren
首先在SDS server上:
ssh -qTfnN -L 7777:10.107.28.250:8080 sl
即:把访问SDS server的7777端口的请求,通过tunnel,转发到10.107.28.250的8080端口上来;
然后在Mac上:
ssh -qTfnN -L 7777:localhost:7777 sdsvm902066.svl.ibm.com
即:把访问Mac的7777端口的请求,通过tunnel,转发到SDS server(即上面的localhost)的7777端口上来;
现在,只需打开浏览器,访问 http://localhost:7777/seyren ,就相当于在SL jumper上访问 http://10.107.28.250:8080/seyren 了。
但是这个方法不具有通用性,对每个URL都要维护2个tunnel和1个端口。
案例4
有些网站在家庭的台式机上无法访问。
解决办法跟案例3非常相似。前提是Mac也处于家庭局域网,并且通过VPN连接到公司内网。网络连通性如下:
台式机 ==> Mac ==> SDS server ==> 网站
首先,在Mac上建立一个到SDS server的动态转发:
ssh -o ExitOnForwardFailure=yes -qTfN -D 8888 kaiding@sdsvm902066.svl.ibm.com
此时,在Mac的浏览器里面设置代理为localhost:8888,就可以在Mac上访问网站了。这其实就是案例2的解决办法。
然后,在台式机上建立一个到Mac的local tunnel:
ssh -o ExitOnForwardFailure=yes -qTfnN -L 8888:localhost:8888 kaiding@192.168.1.8
- 注:192.168.1.8是Mac在局域网的IP地址。
- 注:台式机如果是Win10,则需要一个能运行ssh的工具,比如 Git Bash 。
最后,在台式机的浏览器里设置代理为 localhost:8888 即可。
注:如果希望使用代理服务器的DNS,则需勾选“Proxy DNS when using SOCKS v5”选项。
另外,对于Win10里面的的VMware虚拟机(我用的是Ubuntu),也能通过这个方法访问那些网站。我使用的网络是桥接方式,所以相当于VM也是在同一个局域网内的,其IP地址是 192.168.1.56 。(BTW:Win10的IP地址是 192.168.1.9 )
参考
- https://www.ibm.com/developerworks/cn/linux/l-cn-sshforward/
- https://w3-connections.ibm.com/wikis/home?lang=en-us#!/wiki/Wffbb09234a7a_47cd_bc19_fbbad15fd493/page/Two-layer%20SSH%20reverse%20tunnel
|