一般正规一点的网络环境,大多是这样的:防火墙后分为内网和中立区(DMZ),并且内网和DMZ虽然都能访问外网,互相却是无法直接访问的。内网和DMZ的区别就是,来自外网的访问,都通过防火墙上的规则映射到DMZ里的服务器上,而内网一般是不允许这样的。
现在需要解决的问题就是,在防火墙只能给DMZ开端口,内网和外网不可直接互访的情况下,如果让内网的机器对外提供服务。
ssh是很神奇的,使用它创建的隧道,可以起到代理的作用,数据流的方向是:
本机 -> 隧道 -> 外网
应用到我们的问题中,如果把隧道反过来,就是:
外网 -> DMZ -> 隧道 -> 内网
这就需要用到ssh的反向隧道,它在服务器上打开一个监听端口,这个端口的访问会被隧道传输到本地,结果再通过隧道传到服务器上,从监听端口返回给客户。这样,在我们的应用中,内网机器通过外网访问DMZ服务器,创建ssh反向隧道,就能够对外提供服务了。当然,防火墙上要将相应端口映射到DMZ的服务器上。
比如,在内网登录DMZ服务器:
ssh -R 8082:localhost:82 fwolf@svr5.tld -o ControlPath=/tmp/ssh_svr5_reverse_tunnel
这样,访问DMZ服务器svr5的8082端口,就是在访问本机的82端口。之所以带上-o ControlPath
,是为了和其它访问svr5的进程使用不同的[master模式](385)(如果不是第一次创建这个master,而是使用了原来的连接的sockts,肯定就不会创建隧道了)。
有几个问题还需要注意一下:
- 如果DMZ上监听端口小于1000的话,就必须用root用户登录DMZ服务器,比如
root@svr5.tld
。 - DMZ服务器上的sshd必须开启GatewayPorts选项,在文件
/etc/ssh/sshd_config
中加入GatewayPorts yes
。 - 记得不要idle,参考中有在服务端设置的方法。
- 如果放在其它脚本,比如
/etc/rc.local
中执行的话,除了配置[自动登录](279),还可以带上-fN
参数,放到后台去。
参考
- [TIP SSH Reverse Tunnel](http://gentoo-wiki.com/TIP_SSH_Reverse_Tunnel)
- [ssh reverse tunneling](http://linux.byexamples.com/archives/238/ssh-reverse-tunneling/)
- [PuTTY 中文教程 作者:柴锋 2006年11月](http://chaifeng.com/blog/2007/06/putty_200611.html)
Update @ 2008-07-25
注意,由于使用了反向隧道,所以ssh隧道实际作用相当于一个代理,访问的来源也自然就都成了127.0.0.1
,如果同时还启用了[denyhosts](http://denyhosts.sourceforge.net/),千万记得要把本机地址127.0.0.1
放入白名单/etc/hosts.allow
,不然就会成为其他登录失败的牺牲品(失败的登录,其来源也成了loopback的地址):
ssh_exchange_identification: Connection closed by remote host
Fatal error: Lost connection with the server
没办法,为了网络通道的畅通,只能牺牲一部分安全性了。
NAT – NAT 才是最有意思的事情… 😀
NAT一般要在设备上作吧,在某些情况下不适用 机房管得比较严,开端口都不见得方便,更别说别的了