最近在外地出差,
因为代码服务器放在内网,而因为某些原因,公司的宽带并没有公网地址,所以在外地就没有办法拉取git代码了,
经过多方查找,终于找到了一个好点的解决方案。即使用SSH的返向连接,建立一个临时通道。到我阿里云外网的一台主机上,然后访问阿里云的那台主机就相当于访问内网的这台主机,类拟于建立了一个VPN。
前提条件:有一个外网能访问的主机。操作系统linux A IP是:20.22.22.31
内网有一台也是linux系统,B 192.168.0.10
假设我内网的git 服务器在C上,端口是80 192.168.0.11
做法如下:
在B机器上执行如下命令:
ssh -s -N -R 20.22.22.31:83:192.168.0.11:80 root@20.22.22.31
然后输入密码
这时。在服务器上就可以看到有一个监听了一个83端口:
tcp 0 0 127.0.0.1:83 0.0.0.0:* LISTEN 2734/sshd
这里,就打通了服务器上的83端口到192.168.0.11的80端口的通道。
但这个端口是监听127.0.0.1的,也就是说只能在服务器上能访问,
这是在服务器上,再通过nginx进行端口映射上到外网
在nginx的http里加上:
upstream git {
server 127.0.0.1:83;
}
server{
listen 80;
server_name git.xxx.cn;
location /{
root html;
index index.html index.php;
proxy_pass http://git;
proxy_http_version 1.1;//下面三句支持websocket的反向代理,否则如果网站有websocket的话,会报500错误。
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
这样就可以通过git.xxx.cn来拉代码了。
发果不想通过nginx进行转发,可以开启SSHD的端口转发功能,
vi /etc/ssh/sshd_config
找到:
#GatewayPorts yes
把前面注释去掉。
然后在ssh -s -N -R那条命令上加上以下参数:
-o GatewayPorts=yes
这时,服务器上的83端口监听的域名就变成0.0.0.0:83了 可以很方便的直接进行访问了。可以用ip:83这种方式来访问。
第一步算是通了,但后面还会有问题,
就是网上常说到的,这种方式,一旦连接断开了,就需要能在局域网内进行手动重连,如何自动重连,就需要用到autossh,以及自动登录,
在局域网主机上运行:
ssh-keygen
ssh-copy-id root@20.22.22.31 -p 22
这样以后在这台机器上登录
root@20.22.22.31
就不需要输入密码了。
然后安装 autossh
wget http://fossies.org/linux/privat/autossh-1.4e.tgz
tar zxvf autossh-1.4e.tgz
cd autossh-1.4e
./configure
make
make install
安装 好后,写个脚本:
/usr/local/bin/autossh -p 22 -M 0 -o ServerAliveInterval 10 -o ServerAliveCountMax 3 -NR *:83:192.168.0.10:80 root@20.22.22.31 -i /root/.ssh/id_rsa
为了防止autossh再死掉,可以写个脚本进行进程监控。每隔5分钟,看下这个进程是否还在,如果不在,启动一下。
上面这个脚 本,可以有效防止SSH服务器或网络问题导至的连接中断,网上大多数方案都是autossh -M 1234给个端口号,这个方案好像并不太有效。比如像阿里云服务器,默认SSH好像60秒不操作服务器时,服务端就自动断开连接,他是监听不到的,但我改成这种方式,就没问题了。
其中参数部分:
-o ServerAliveInterval 10 -o ServerAliveCountMax 3
这个是指autossh创建ssh连接时,这个连接会每10秒会发送一个消息,服务器如果在3次发送消息还没回应,则会断开,当这个连接断开后,openssh又会重新启一个连接,这样就能保证连接不会中断。