又一种访问内部服务的方法
2014-06-22 13:09:09 阿炯

通常要从外部访问内部机器上的服务的方法,是在网关上做一个端口转发,如果网关的公网ip是固定的,直接访问就可以,否则还要取得网关的ip地址(使用Perl来对dnspod进行记录自动更新)。本文就是在网关上不能开启端口转发服务,或根本就不能控制网关的情况下,从固定的ip访问内网的服务。

注意:需要一台在公网的linux服务器。

在idc机房有几十台linux服务器,由于大部分机器不需要公网ip,所以它们之间有一个内网,为了方便对它们的管理,我在一台服务器用virtualbox虚拟了一台vyatta软路由,它有两个网口,它们分别桥接在服务器的内外网。

实现方法
让内网的机器主动通过vpn拨号的idc机房中软路由上,软路由为其分配一个与其它服务器内网同段的内网地址,这样内网的机器就可与位于idc机房内的公网的内网直接通信;在其它有公网ip的机器或直接在软路由上作一个端口转发服务,当访问该端口的服务时,实际是访问到了内网机器上的服务。

需要在软路由上建立vpn帐号,设定使用的方式,内网机器上需要布置好拨号脚本(如下)。

在vyatta上使用l2tp方式设置vpn登录,请参考:Vyatta下vpn使用设置之l2tp Debian下配置l2tp vpn客户端

在外网的机器做端口转发,使用rinet来实现。

linux下端口转发映射的程序叫rinetd,启动方法rinetd -c /etc/rinetd.conf,pkill rinetd 关闭进程。

工具主页: http://www.boutell.com/rinetd/

软件下载,解压安装

wget http://www.boutell.com/rinetd/http/rinetd.tar.gz
tar zxvf rinetd.tar.gz
make
make install

把1.1.1.1的11端口映射到2.2.2.2的3389端口,配置文件如下

[root@localhost freeoa]# cat /etc/rinetd.conf

1.1.1.1 11 2.2.2.1 3389
59.33.120.36 80 192.168.0.72 80
1.1.1.1 6022 2.2.2.3 22
1.1.1.1 14 2.2.2.4 80
allow *.*.*.*
allow 59.33.120.*

logfile /var/log/rinetd.log
logfile /var/log/rinetd.log

启动程序
pkill rinetd  ##关闭进程
rinetd -c /etc/rinetd.conf ##启动转发

把上页这条命令加到/etc/rc.local里面就可以开机自动运行。

查看状态
netstat -antup

拨号脚本内容如下:
use 5.012;
use Net::Ping;
use IO::Interface::Simple;

my @interfaces = IO::Interface::Simple->interfaces;
#vpn登录成功后,vpn网关的地址
my ($ga)=('192.168.30.251');

my $ping=Net::Ping->new();

#check the vpn gateway is alive
sub chk_ga_state{
 if($ping->ping($ga)){
  #ping result is ok
  return 1;
 }else{
  return 0;
 }
}#end fun

#if gate way can't connect,start the vpn dial up
if(chk_ga_state){
 #the vpn network is up
 say 'the ppp vpn connection is ok,^_^.';
}else{
 #if the ppp interface exist,disconnect it
 say 'vpn gateway has down,we will start it.';
 if(grep 'ppp0',@interfaces){
  say 'disconnect the died vpn conn';
  system(qq{echo 'd freeoa_vpn' > /var/run/xl2tpd/l2tp-control});
 }
 #create the ppp conn
  say 'create ppp conn.';
  system(qq{echo 'c freeoa_vpn' > /var/run/xl2tpd/l2tp-control});
  sleep(2);
  if(grep 'ppp0',@interfaces){
   say 'ppp interface create succeed.';
   say 'add ppp vpn route.';
   system(q{/sbin/route add -net 192.168.30.0 netmask 255.255.255.0 dev ppp0});
  }
}

END{
 $ping->close();
}


我将它保存后,加其加入的crontab中。这样就可以从固定的ip和端口访问内网中机器上的服务。