概述
现在的家庭宽带或者部分公司的宽带都没有直接分配公网 IP ,这个给我们做开发调试时带来的很大的不便,比如我们需要对接微信公众号、支付宝等第三方系统时,第三方系统需要通过异步回调通知我们的服务,但是我们自己电脑上的应用程序都无法对外访问,这样也就通知不了,无法很好的进行联调测试。
在这样的背景下,ngrok 对于我们来说就提供了很大的帮助,他可以让我们内网的应用可以对外访问,无论是 HTTP(s) 服务还是 TCP/SSH 等场景,均可以通过 ngrok 服务内网穿透来达到对外提供访问的目的。
搭建步骤
第一步:安装 golang 环境
博主的服务器统一使用的 CentOS 7 发行版本,所以通过 yum install golang
就可以安装好 golang 环境,如果是其他操作系统可以参考官方文档 How to install golang
第二步:下载 ngrok 源码
目前 ngrok 2.x 版本已经闭源,我们能下载到的最新版本为 ngrok-1.7.1.zip,
下载完成之后解压 zip 包,这里我们需要修改 src/ngrok/log/logger.go
中的源代码,
将 log "code.google.com/p/log4go"
修改为 log "github.com/alecthomas/log4go"
,
否则编译时会报错 build fails: 'package code.google.com/p/log4go: unable to detect version control system for code.google.com/ path'
第三步:生成 TLS 证书
例如我们以 4kb.cn 域名为例,我们在生成证书的时候可以指定 ngrok.4kb.cn 这个域名指定 ngrok 服务器地址(需要 DNS 解析到 ngrok 所在服务器的 IP 上),同时我们对外提供 ngrok 域名为 .4kb.cn (需要泛域名解析 .4kb.cn 到 ngrok 所在服务器的 IP 上),这里的 ngrok.4kb.cn 和 *.4kb.cn 解析并不冲突。
生成 TLS 证书的命令如下:
openssl genrsa -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -subj "/CN=ngrok.4kb.cn" -days 3650 -out rootCA.pem
openssl genrsa -out device.key 2048
openssl req -new -key device.key -subj "/CN=ngrok.4kb.cn" -out device.csr
openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 3650
第四步:覆盖 ngrok 默认 TLS 证书
cp rootCA.pem assets/client/tls/ngrokroot.crt
cp device.crt assets/server/tls/snakeoil.crt
cp device.key assets/server/tls/snakeoil.key
第五步:设置 Golang 编译目录和参数
export GOPATH=/go
为了可以在 docker 环境下运行,我们还需要运行下面的命令,否则会报错 Unable to run a go program inside docker /bin/sh: ./ngrokd: not found
export CGO_ENABLED=0
第六步:编译 ngrok 服务端和客户端
Linux 32 位系统 ngrok 编译命令
export GOOS=linux GOARCH=386
make release-server release-client
Linux 64 位系统 ngrok 编译命令
export GOOS=linux GOARCH=amd64
make release-server release-client
Windows 32 位系统 ngrok 编译命令
export GOOS=windows GOARCH=386
make release-server release-client
Windows 64 位系统 ngrok 编译命令
export GOOS=windows GOARCH=amd64
make release-server release-client
macOS 32 位系统 ngrok 编译命令
export GOOS=darwin GOARCH=386
make release-server release-client
macOS 64 位系统 ngrok 编译命令
export GOOS=darwin GOARCH=amd64
make release-server release-client
其他操作系统修改 GOOS 和 GOARCH 为对应的即可:Go (Golang) GOOS and GOARCH
第七步:运行 ngrokd 服务端
编译完成之后可以在 bin 目录下看到 ngrokd(服务端)和 ngrok(客户端),运行服务端时需要将 assets/server/tls/snakeoil.crt 和 assets/server/tls/snakeoil.key
复制到同级目录,启动的命令参考如下:
./ngrokd -tlsKey=snakeoil.key -tlsCrt=snakeoil.crt -domain="4kb.cn" -httpAddr=":80" -httpsAddr=":443" -tunnelAddr=":4443"
如果使用默认 80、443、4443 端口,则可以使用以下命令运行:
./ngrokd -tlsKey=snakeoil.key -tlsCrt=snakeoil.crt -domain="4kb.cn"
第八步:运行 ngrok 客户端
运行之前我们需要编写一个 ngrok.cfg
文件,内容如下
server_addr: "ngrok.4kb.cn:4443"
trust_host_root_certs: false
这里的 server_addr 需要和第三步生成 TLS 时保持一致,否则服务端会报 tls: bad certificate
证书错误,
编辑完成之后使用 ngrok 客户端运行即可
./ngrok -config=ngrok.cfg 8080
指定域名运行命令
./ngrok -config=ngrok.cfg -subdomain=xxx 8080
映射 SSH 22 端口,使用 tcp 协议
./ngrok -config=ngrok.cfg -proto=tcp 22
总结
我们搭建完成 ngrok 服务端后,任意能连接到服务器的应用程序均可以通过 ngrok 内网穿透,不仅 Java、PHP 等开发的网站可以通过 ngrok 映射对外提供域名访问,也可以让 SSH 的 22 端口映射之后,我们连接无公网 IP 的服务器(比如在家里面搭建一个私有服务器),甚至还可以将 MySQL 的 3306 端口映射之后,在任意地点远程连接内网的数据库。这给我们带来来极大的方便,也不需要购买第三方服务(例如花生壳)。
参考文献
- 编译自己的ngrok服务
- Go (Golang) GOOS and GOARCH
- Unable to run a go program inside docker /bin/sh: : not found
版权
版权声明:*转载-非商用-非衍生-保持署名(创意共享3.0许可证)
原创作者 10086@xiaoi.me 发表于阿里云·云栖社区:https://yq.aliyun.com/users/y4epujtm5wye6
扫码关注我,在线与我沟通、咨询
转载请保留原文链接以及版权信息