咸鱼

咸鱼是以盐腌渍后,晒干的鱼

0%

自建ngrok服务内网穿透

使用场景
  1. 个人PC电脑上调试 微信公众号微信web开发者工具 需要公网域名。
  2. ngrok将个人PC电脑的端口暴露到公网

本来用 nginx反向代理 + 路由器的虚拟服务器转发 可以很方便的解决这个场景,但最近公司路由器抽风,一直不好使。

官方的ngrok很不稳定,偶尔可以用。自建ngrok服务相对稳定,但要自己编译服务端和客户端的二进制文件。

最终效果

公网访问 http://debug.mydomain.com 或者 https://debug.mydomain.com ,将直接访问到部署在我的PC电脑上的Tomcat服务,方便调试程序。

部署环境
  1. 公网阿里云 ESC,系统 CentOS(假设域名:mydomain.com)
  2. 公司内的开发笔记本,系统 Win10

我们将在服务器内编译二进制文件,下载到Win10运行。

安装编译环境
1
$ yum install -y perl-ExtUtils-MakeMaker mercurial golang

如果是Ubuntu系统

1
$ apt-get install build-essential mercurial golang
下载ngrok源码
1
2
3
$ cd /opt
$ git clone https://github.com/inconshreveable/ngrok.git ngrok
$ cd ngrok
创建自签名证书
1
2
3
4
5
6
7
8
9
$ NGROK_DOMAIN="mydomain.com"
$ openssl genrsa -out base.key 2048
$ openssl req -new -x509 -nodes -key base.key -days 10000 -subj "/CN=$NGROK_DOMAIN" -out base.pem
$ openssl genrsa -out server.key 2048
$ openssl req -new -key server.key -subj "/CN=$NGROK_DOMAIN" -out server.csr
$ openssl x509 -req -in server.csr -CA base.pem -CAkey base.key -CAcreateserial -out server.crt -days 5000
$ cp server.crt assets/server/tls/snakeoil.crt
$ cp server.key assets/server/tls/snakeoil.key
$ cp base.pem assets/client/tls/ngrokroot.crt
编译
1
2
3
4
5
6
# 服务端 bin/ngrok
$ make release-server
# win64
$ GOOS=windows GOARCH=amd64 make release-client
# mac
$ GOOS=darwin GOARCH=amd64 make release-client
启动服务端

由于服务器环境中已有nginx存在,所以,这里的ngrok采用 70707071 端口。

1
2
3
4
5
$ /opt/ngrok/bin/ngrokd -tlsKey=/opt/ngrok/server.key -tlsCrt=/opt/ngrok/server.crt -domain=mydomain.com -httpAddr=:7070 -httpsAddr=:7071 -tunnelAddr=:7443 > /opt/ngrok/ngrok.log &
$ netstat -tnlp
tcp 0 0 0.0.0.0:7070 LISTEN 12816/ngrokd
tcp 0 0 0.0.0.0:7071 LISTEN 12816/ngrokd
tcp 0 0 0.0.0.0:7443 LISTEN 12816/ngrokd
配置阿里云控制台
  1. 端口开放

    在阿里云的 安全组规则 配置好 入方向 的端口 ,如将 7070/8080 范围对外开放。

  2. 域名解析

    debug.mydomain.com 指向我们的服务器IP地址 。

配置服务器nginx反向代理

如果服务器没有其他服务,则可以跳过这一步,直接给ngrok用80端口。

微信公众号开发 必须采用80和443端口,反向代理是为了将 debug.mydomain.com:80 流量转发到 -> ngrok-server(7070,7071)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
map $scheme $proxy_port {
"http" "7070";
"https" "7071";
default "7070";
}

server {
listen 80;
#listen [::]:80;
listen 443;
#listen [::]:443;
server_name debug.mydomain.com;

location / {
resolver 114.114.114.114 valid=2s;
proxy_pass $scheme://$host:$proxy_port;
proxy_redirect off;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 6 128k;
proxy_busy_buffers_size 256k;
proxy_temp_file_write_size 256k;
}

ssl on;
ssl_certificate /opt/ngrok/server.crt;
ssl_certificate_key /opt/ngrok/server.key;

access_log off;
log_not_found off;
}
客户端

下载相关平台的客户端放在一目录下,如win64的 ngrok.exe 。同目录下新建文本 ngrok.cfg,内容为

1
2
server_addr: debug.mydomain.com:7443
trust_host_root_certs: false

假设我本地笔记本跑了一个Tomcat,端口为8080 ,运行ngrok的命令如下:

1
$ ngrok.exe  -subdomain debug -proto=http -config=./ngrok.cfg 8080

其中 debug 是我的子域名,在浏览器打开 http://debug.mydomain.com ,如果能访问 Tomcat 的页面,就OK了。

流量入流路由如: server-nginx -> server-ngrok -> client-ngrok -> tomcat

访问 http://127.0.0.1:4040 (ngrok的页面),可以看到所有来自外部的请求内容。

本地前/后端分离

如果本地笔记本有多个服务,可以在本地再搭建一个 nginx ,通过反向代理转发实现流量转发。

比如:我架构是 Vue + Tomcat 实现了前后端分离,Vue 的端口为 1234Tomcat 端口依然为 8080nginx 端口为 80 ,我们要将 ngrok 启动的端口改为 nginx80 端口。

1
$ ngrok.exe  -subdomain debug -proto=http -config=./ngrok.cfg 80

流量入流路由如: server-nginx -> server-ngrok -> client-ngrok -> pc-nginx -> (vue + tomcat)

本地PC nginx 配置文件中增加一个虚拟服务器,配置如下:

1
2
3
4
5
6
7
8
9
10
server {
listen 80;
server_name localhost;
location /wx {
proxy_pass http://localhost:8080/wx/;
}
location / {
proxy_pass http://localhost:1234;
}
}

nginx/wx 路径的转发到 Tomcat/wx 以外的路径请求全部转发给 Vue

总结

后续只需要启动 ngrok-server 和 ngrok-client 就可以打通公网与PC机的网络。如果要开辟新的子域名,则需要添加新的域名记录。

大量域名技巧: 编译基础域名设置为 debug.mydomain.com ,采用 *.debug.mydomain.com 作为 server-nginx 的name ,具体查看旧的commit记录。

参考:阿里云主机CentOS 7下编译安装ngrok