Ngrok 是一个反向代理,可以将本地的web或tcp服务通过公共端口和外部建立一个安全通道,这样就可以通过外网直接访问本地对应的服务,在进行微信公众号等测试开发的时候非常有用
域名解析
将需要外网访问的域名解析到所部署的服务器上,为了支持多级域名需要进行泛解析。比如ngrok的域名使用 ngrok.example.com
的话,需要将 ngrok.example.com
和 *.ngrok.example.com
域名的A记录解析到所部署的服务器IP上,这样客户端就可以使用如 jet.ngrok.example.com
这样的域名进行访问了。
编译安装ngrok
安装GO环境
参考:Go 环境部署和开发工具及常见问题
安装后版本:
[root@xiexianbin_cn src]# go version
go version go1.11.4 linux/amd64
下载 Ngrok
ngrok
项目的官方地址是:https://github.com/inconshreveable/ngrok
获取源码:
cd /usr/local/src
git clone https://github.com/tutumcloud/ngrok.git
域名证书
域名证书可以到 SSL 证书提供商获取,也可以自己生成签名证书,步骤如下:
需要将NGROK_DOMAIN
替换为自己的域名
cd $GOPATH/src/github.com/inconshreveable/ngrok
NGROK_DOMAIN="p.80.xyz"
openssl genrsa -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -subj "/CN=$NGROK_DOMAIN" -days 5000 -out rootCA.pem
openssl genrsa -out device.key 2048
openssl req -new -key device.key -subj "/CN=$NGROK_DOMAIN" -out device.csr
openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 5000
cp rootCA.pem assets/client/tls/ngrokroot.crt
cp device.crt assets/server/tls/snakeoil.crt
cp device.key assets/server/tls/snakeoil.key
编译并启动服务端
ngrokd
为服务端的执行文件,ngrok
为客户端的执行文件,我们先来编译ngrok
的服务端程序,在ngrok
目录下面执行下面的命令:
make release-server
[root@xiexianbin_cn ngrok]# make release-server
GOOS="" GOARCH="" go get github.com/jteeuwen/go-bindata/go-bindata
bin/go-bindata -nomemcopy -pkg=assets -tags=release \
-debug=false \
-o=src/ngrok/client/assets/assets_release.go \
assets/client/...
bin/go-bindata -nomemcopy -pkg=assets -tags=release \
-debug=false \
-o=src/ngrok/server/assets/assets_release.go \
assets/server/...
go get -tags 'release' -d -v ngrok/...
github.com/inconshreveable/mousetrap (download)
github.com/rcrowley/go-metrics (download)
Fetching https://gopkg.in/inconshreveable/go-update.v0?go-get=1
Parsing meta tags from https://gopkg.in/inconshreveable/go-update.v0?go-get=1 (status code 200)
get "gopkg.in/inconshreveable/go-update.v0": found meta tag get.metaImport{Prefix:"gopkg.in/inconshreveable/go-update.v0", VCS:"git", RepoRoot:"https://gopkg.in/inconshreveable/go-update.v0"} at https://gopkg.in/inconshreveable/go-update.v0?go-get=1
gopkg.in/inconshreveable/go-update.v0 (download)
github.com/kardianos/osext (download)
github.com/kr/binarydist (download)
Fetching https://gopkg.in/inconshreveable/go-update.v0/check?go-get=1
Parsing meta tags from https://gopkg.in/inconshreveable/go-update.v0/check?go-get=1 (status code 200)
get "gopkg.in/inconshreveable/go-update.v0/check": found meta tag get.metaImport{Prefix:"gopkg.in/inconshreveable/go-update.v0", VCS:"git", RepoRoot:"https://gopkg.in/inconshreveable/go-update.v0"} at https://gopkg.in/inconshreveable/go-update.v0/check?go-get=1
get "gopkg.in/inconshreveable/go-update.v0/check": verifying non-authoritative meta tag
Fetching https://gopkg.in/inconshreveable/go-update.v0?go-get=1
Parsing meta tags from https://gopkg.in/inconshreveable/go-update.v0?go-get=1 (status code 200)
Fetching https://gopkg.in/yaml.v1?go-get=1
Parsing meta tags from https://gopkg.in/yaml.v1?go-get=1 (status code 200)
get "gopkg.in/yaml.v1": found meta tag get.metaImport{Prefix:"gopkg.in/yaml.v1", VCS:"git", RepoRoot:"https://gopkg.in/yaml.v1"} at https://gopkg.in/yaml.v1?go-get=1
gopkg.in/yaml.v1 (download)
github.com/inconshreveable/go-vhost (download)
github.com/alecthomas/log4go (download)
github.com/nsf/termbox-go (download)
github.com/mattn/go-runewidth (download)
github.com/gorilla/websocket (download)
go install -tags 'release' ngrok/main/ngrokd
[root@xiexianbin_cn ngrok]#
首次编译时间有一些长。编译成功之后会在项目目录的bin目录下面生成一个 ngrokd 的文件,使用下面的命令启动服务:
bin/ngrokd -domain="ngrok.example.com" -httpAddr=":8080" -httpsAddr=":8443" -tunnelAddr=":4443"
参数说明:
- domain 表示服务的域名
- httpAddr 表示HTTP的端口
- httpsAddr 表示HTTPS的端口
- tunnelAddr 用来设置通道的端口,在客户端和服务端建立连接的端口,需要在防火墙中开放次端口(默认为4443)
可以将命令加入到 ``/etc/rc.local` 中使其开机启动,命令如下:
/usr/local/src/ngrok/bin/ngrokd -domain="ngrok.80.xyz" -httpAddr=":8080" -httpsAddr=":8443" -tunnelAddr=":4443" > /dev/null 2>&1 &
其中 ``/usr/local/ngrok 是
ngrok`的安装目录,最后不显示运行的日志,并且在后台运行。
客户端
编译客户端
首先进入项目的根目录,使用下面的命令编译专用的客户端文件:
GOOS=windows GOARCH=amd64 make release-client
GOOS=darwin GOARCH=amd64 make release-client
GOOS=linux GOARCH=amd64 make release-client
其中GOOS
用乱设置操作系统,GOARCH
用来设置对应的架构(386,amd64或arm),其含义如下:
- Linux 平台 32 位系统:GOOS=linux GOARCH=386
- Linux 平台 64 位系统:GOOS=linux GOARCH=amd64
- Windows 平台 32 位系统:GOOS=windows GOARCH=386
- Windows 平台 64 位系统:GOOS=windows GOARCH=amd64
- MAC 平台 32 位系统:GOOS=darwin GOARCH=386
- MAC 平台 64 位系统:GOOS=darwin GOARCH=amd64
- ARM 平台:GOOS=linux GOARCH=arm
上面的命令表示编译windows
下使用的32位``的客户端程序,编译好的文件在
bin`目录下对应平台的目录下面。
启动客户端
接下来就可以使用客户端了,首先创建一个ngrok
的配置文件ngrok.cfg
:
server_addr: "ngrok.example.com:4000"
trust_host_root_certs: false
域名后面的端口是设置的通道端口。
接下来使用下面的命令运行客户端:
./ngrok -subdomain jet -config=ngrok.cfg 8080
其中jet
是自定义的域名前缀,ngrok.cfg
是上面的配置文件,8080
是映射的本地到外网的端口,这样就可以使用 http://jet.ngrok.example.com:8088
访问本地8080
的端口了。
另外,还可以使用 -proto
来指定协议的类型(默认是http协议),支持http
、tcp
等多种协议:
./ngrok -subdomain jet -config=ngrok.cfg -proto=tcp 8080
使用Nginx反向代理到80端口
上面通过子域名访问的时候不是默认的80端口,可以使用Nginx进行反向代理,配置信息如下:
upstream ngrok_server {
server 127.0.0.1:8088 weight=1 max_fails=3 fail_timeout=30s;
keepalive 64;
}
server {
listen 80;
server_name *.ngrok.example.com ngrok.example.com;
charset utf-8;
location / {
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_set_header Host $host:8088;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://ngrok_server;
proxy_redirect off;
}
access_log off;
log_not_found off;
}
上面例子中的8088
即ngrok
设置的httpAddr
参数设置的端口,有两处。这样就可以直接使用域名的80端口访问了。
其他实现软件
- Tailscale 是一种
VPN(Virtual Private Network)
服务,可以让您在世界任何地方安全、轻松地访问您拥有的设备和应用程序,它使用开源 WireGuard 协议实现加密的点对点连接
- ZeroTier
- localtunnel