搭建自己的ngrok服务来内网穿透
开发的过程中偶尔会需要内网外的服务器能找到自己的电脑, 而自己的电脑在公司内只有内网地址, 没有独立的公网地址。这种情况还是比较常见的, 比如调试第三方服务接口需要回调时, 比如微信第三方登录接入等, 另外, 自己在家如果想访问公司内的服务器也是一样的障碍。
这个痛点怎么解决呢?——内网穿透!
内网穿透的方法不止一种, 今天我介绍下利用ngrok服务来穿透的方法。
ngrok 原理简介
虽然内网中的服务器A不能被外部的网络C发现, 但却可以主动去联系外部的网络(没被注意到就主动点嘛:), 哈哈)。 所以, 我们如果有一个部署在公网的服务器B,A 主动连接B建立起一个隧道, 那么C就可以通过B找到A啦!
如上图所示, ngrokd部署在B上, 作为通道的服务端, ngrok部署在A上, 作为连接B的客户端。
自己搭建ngrok服务器
ngrok 作者提供了公共的ngrokd服务(太赞了), 不过为了更加稳定和安全的使用, 还是搭建一个自己的ngrokd服务更加稳妥。搭建的唯一要求就是有一台部署在公网中的服务器和自己的域名, 我博客的vps刚好可以拿来用用。
首先, 安装依赖环境
如果是 ubuntu:
1
sudo apt-get install build-essential golang mercurial
如果是 centos
1
2
3
yum install gcc gcc-c++ make
yum install golang
yum install mercurial
如果是mac(macmini作为服务器也是有的)
1
2
brew install golang
brew install mercurial
自签名证书
先把代码克隆岛本地
1
2
git clone https://github.com/inconshreveable/ngrok.git ngrok
cd ngrok
假设你的域名是 abc.com
, 你可以把ngrok服务的根域名设置为 tunnel.abc.com
, 当然, 你也可以设置成其它。
ngrok通道之间传输的数据是经过SSL加密的,所以我们要准备好证书, 如果自己没有申请过证书的话,可以生成个自签的证书来自用。
1
2
3
4
5
openssl genrsa -out base.key 2048
openssl req -new -x509 -nodes -key base.key -days 10000 -subj "/CN=tunnel.abc.com" -out base.pem
openssl genrsa -out server.key 2048
openssl req -new -key server.key -subj "/CN=tunnel.abc.com" -out server.csr
openssl x509 -req -in server.csr -CA base.pem -CAkey base.key -CAcreateserial -days 10000 -out server.crt
记得把tunnel.abc.com 换成自己的域名。 上边运行成功后, 应该能在当前目录下看到以下生成的文件:
1
2
3
4
5
6
- base.key
- base.pem
- base.srl
- server.crt
- server.csr
- server.key
用生成的证书替换ngrok的默认证书:
1
cp base.pem assets/client/tls/ngrokroot.crt
域名DNS配置
我的域名是从godaddy上购买的, 所以需要新增两个A类型的配置: tunnel.abc.com 指向自己vps的ip *.tunnel.abc.com 指向自己vps的ip
因为http/https服务是随机生成域名前缀的, 所以用*.tunnel来匹配, 另外, 千万不要忘了额外添加tunnel.abc.com, 我自己就是因为少了这一条结果调试了好久, 发现建立连接的时候无法解析tunnel.abc.com的域名。
生成可执行文件
1
make release-server release-client
赋予可执行权限:
1
2
chmod +x bin/ngrokd
chmod +x bin/ngrok
生成的可以执行文件在bin目录下, 把可执行文件和证书拷贝到一个目录里
1
2
3
4
5
6
mkdir ngrok-bin
cd ngrok-bin
cp ../bin/ngrok ngrok
cp ../bin/ngrokd ngrokd
cp ../server.crt server.crt
cp ../server.key server.key
启动
在vps上启动ngrokd:
1
./ngrokd -tlsKey=server.key -tlsCrt=server.crt -domain=tunnel.abc.com -httpAddr=":8080" -httpsAddr=":8081"
这时候打开浏览器, 输入:http://random.tunnel.abc.com:8080, 如果出现以下界面则说明启动成功:
接下来启动客户端: 把ngrok可执行文件拷贝到客户端, btw, 如果你的服务端是centos, 客户端是mac, 则你需要把证书拷贝下来, 在客户端重新生成一遍客户端可执行文件
1
make make release-server release-client
配置启动文件: vim ngrok.cfg, 写入如下内容:
1
2
server_addr: tunnel.abc.com:4443 # 默认的通道端口
trust_host_root_certs: false # 自签的证书要设置为false
启动客户端:
1
./ngrok -subdomain testing -config=ngrok.cfg 80
如果显示 tunnel status 为online 则启动成功。
ssh 配置
ngrok 其实不止可以用于http穿透, 其实通道是基于TCP的, 所以我们开放任意的TCP端口, 所以如果我们开放22端口就可以在C机器上ssh内网中的A机器里了。配置如下:
1
2
3
4
5
6
7
8
9
10
11
server_addr: tunnel.abc.com:4443
trust_host_root_certs: false
tunnels:
http:
subdomain: "ldy" # 可以自定义
proto:
http: "80"
ssh:
remote_port: 50005 # 可以自定义
proto:
tcp: "22" # 如果ssh不是默认端口22, 可以更改
启动:
1
./ngrok -config=ngrok.cfg start ssh
运行后, 在外网中就可以ssh到内网中的机器了:
1
ssh username@tunnel.abc.com -p 50005
参考文章
ngrok run ngrok on your own server ngrok 原理