内网穿透利器ngrok部署配置指南
📅 2019-10-30 | 🖱️
ngrok是使用go语言开发的反向代理服务,可以在公共的端点和本地内网的Web服务之间建立一个安全通道,实现内网穿透功能。 虽然ngrok 2.x的版本已经闭源,但ngrok 1.x还是开源的,版本停留在了1.7不再开发和维护,但它作为个人平时开发和调试的内网穿透工具偶尔使用还是够用的。之前小白的ngrok部署在个人的一台AWS EC2主机上已有好几年,最近这台EC2释放掉了,小白需要在新的主机上部署ngrok服务,正好借着这个机会整理一下ngrok的部署和配置过程。
0.前提条件 #
- 一台Linux云主机(这里是CentOS 7),并要求具有固定公网IP暴露这台云主机指定端口的能力
- 有一个域名解析到这个公网IP,如
ngrok.frognew.com
和*.ngrok.frognew.com
解析到这个公网IP
1. 编译ngrok服务端ngrokd和客户端ngrok #
首先需要从ngrok 1.x的源码编译ngrok的服务端ngrokd和客户端ngrok程序。ngrok使用golang开发,这里先在这台新的云主机上安装Go语言。 这台云主机是CentOS 7,这里直接使用yum安装golang:
1yum install golang
yum安装完成的go,会自动创建/usr/bin/go到安装目录的软链接,所以这里不再配置环境变量。
接下来使用git clone ngrok 1.x的源码:
1cd /usr/local
2git clone https://github.com/inconshreveable/ngrok.git
3cd ngrok
因为这里ngrok服务的域名是ngrok.frognew.com
,接下来为这个域名生成ngrok服务端和客户端的证书:
1export NGROK_DOMAIN=ngrok.frognew.com
2
3openssl genrsa -out rootCA.key 2048
4openssl req -x509 -new -nodes -key rootCA.key -subj "/CN=$NGROK_DOMAIN" -days 5000 -out rootCA.pem
5openssl genrsa -out device.key 2048
6openssl req -new -key device.key -subj "/CN=$NGROK_DOMAIN" -out device.csr
7openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 5000
使用生成的证书替换ngrok源码中的证书:
1cp rootCA.pem assets/client/tls/ngrokroot.crt
2cp server.crt assets/server/tls/snakeoil.crt
3cp server.key assets/server/tls/snakeoil.key
编译ngrok的服务端ngrokd:
1export GOPATH=/usr/local/ngrok
2export GOOS=linux
3export GOARCH=amd64
4make release-server
按需编译ngrok的客户端ngrok,小白这里是Mac所以只编译Mac OS系统的客户端:
1GOOS=darwin GOARCH=amd64 make release-client
关于golang的交叉编译,通过
GOOS
指定对应操作系统,darwin
对应Mac OS,windows
对应Windows,linux
对应Linux.
2. 配置启动服务端ngrokd #
接下来配置启动服务端ngrokd,创建一个非特权用户ngrok作为服务端的运行用户:
1useradd ngrok
编写ngrokd的Systemd配置文件/etc/systemd/system/ngrokd.service:
1[Unit]
2Description=ngrok server
3After=network.target
4[Service]
5Type=simple
6User=ngrok
7ExecStart=/usr/local/ngrok/bin/ngrokd --domain=ngrok.frognew.com --tunnelAddr=:14443 --httpAddr=:8081 --httpsAddr=
8Restart=on-failure
9[Install]
10WantedBy=multi-user.target
ngrokd包含了下面的启动参数:
--domain
ngrok的域名,也是前面生成证书时用到的那个域名--httpAddr
http协议端口,默认为80,这里修改为8081,--httpsAddr
https协议端口 默认为443,这里修改空表示不监听和使用https端口--tunnelAddr
通道端口 默认4443,这里修改为14443
注: 关于http协议只启用了http,是因为这里并不会通过公网IP直接暴露8081这个端口,而在ngrokd前面会部署一个nginx暴露80和443,nginx通过443做TLS Termination,所以--httpsAddr
就不再需要了。
启动ngrokd:
1systemctl enable ngrokd
2systemctl start ngrokd
3
4netstat -nltp | grep ngrokd
5tcp6 0 0 :::14443 :::* LISTEN 8485/ngrokd
6tcp6 0 0 :::8081 :::* LISTEN 8485/ngrokd
3.nginx配置 #
接下来配置nginx反向代理ngrokd的http服务:
1server {
2 listen 80;
3 server_name *.ngrok.frognew.com;
4 rewrite ^(.*)$ https://$host$1 permanent;
5}
6
7
8server {
9 listen 443 ssl;
10 server_name *.ngrok.frognew.com;
11 proxy_set_header X-Real-IP $remote_addr;
12 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
13 proxy_set_header Host $http_host:8081;
14 proxy_set_header X-Nginx-Proxy true;
15 proxy_set_header Connection "";
16
17 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
18 ssl_certificate /etc/letsencrypt/live/frognew.com/fullchain.pem;
19 ssl_certificate_key /etc/letsencrypt/live/frognew.com/privkey.pem;
20 location / {
21 # proxy_intercept_errors on;
22 # error_page 404 /404.html;
23 proxy_pass http://127.0.0.1:8081;
24 }
25
26}
4.ngrok客户端配置 #
使用python3在本地快速启动一个http服务用于测试:
1python3 -m http.server 8080
下面将使用ngrok将这个http服务暴露到公网,将前面编译的ngrok客户端ngork
可执行文件下载到本地。
编写ngrok的客户端配置文件ngrok.yml:
1server_addr: ngrok.frognew.com:14443
2trust_host_root_certs: false
3tunnels:
4 py-http-demo:
5 proto:
6 http: 8080
启动ngrok客户端:
1./ngrok -config ngrok.yml start py-http-demo
2
3Tunnel Status online
4Version 1.7/1.7
5Forwarding http://py-http-demo.ngrok.frognew.com:8081 -> 127.0.0.1:8080
6Web Interface 127.0.0.1:4040
7# Conn 0
8Avg Conn Time 0.00ms
使用http://py-http-demo.ngrok.frognew.com
即可从公网访问前面使用python启动的用于测试的http服务。