概述
研究了下 ngrok 的使用,坑还是挺多,随后再看看源码吧,看是否能做些修改和定制
疑问1: 是否能支持 ecc 证书,目前用的脚本生成的自签RSA证书
经过测试ngrok客户端+服务器支持 ecc证书。
疑问2: 性能如何?
需要分析源码,完善优化
好了,开始吧。
1. 当前git上开源的代码版本,号称是1.0x版本,其实是2.1.7
const (
Proto = "2"
Major = "1"
Minor = "7"
)
下载ngrok源码(ngrok代理服务的server/client都在同一份代码中),git上的最新版本是2.1.7,但是ngrok官方最新代码已经闭源,旧代码 凑合还能用。server和client,自己编译,证书自己搞定吧
git clone https://github.com/inconshreveable/ngrok.git
2. 解压ngrok源码,mv ./ngork 到 /usr/local/ngrok 下
3. cd /usr/local/ngrok
我的服务器环境:
[root@localhost ngrok]# cat /etc/redhat-release
CentOS Linux release 7.5.1804 (Core)
[root@localhost ngrok]# go version
go version go1.9.4 linux/amd64
我的客户端运行环境: windows7 X64 SP1
4. 创建服务器自签名证书
在 /usr/local/ngrok 目录下
创建 work.sh 脚本,用来创建服务器自签名证书,内容如下:
#!/bin/bash
#生成并替换源码里默认的证书,注意域名要修改为你自己的,这里是一个虚拟的测试域名
NGROK_DOMAIN="dev.mydomain.com"
#测试一下有没有设置成功
echo $NGROK_DOMAIN #输出ngrok.xxx.com表示成功
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 server.key 2048
openssl req -new -key server.key -subj "/CN=$NGROK_DOMAIN" -out server.csr
openssl x509 -req -in server.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out server.crt -days 5000
rm -rf ./server.csr
创建自签名证书有个重要的点,需要注意 work.sh 内的 NGROK_DOMAIN 可以设置为自己的域名,随后客户端配置文件ngrok.cfg内 server_addr 后面填写的域名也必须是 NGROK_DOMAIN 的值
5. 证书生成完后,需要拷贝指定证书到指定的位置
下一步也就是第6步,ngrok通过bindata第三方库,将ngrok源码目录下的assets目录(资源文件)打包到可执行文件(ngrokd和ngrok)中 去,assets/client/tls和assets/server/tls下分别存放着用于ngrok和ngrokd的默认证书文件,我们需要将它们替换成我们自己生成的:(因此这一步务必放在编译可执行文件之前)
#拷贝客户端要使用的签发服务器的根证书,也就是根证书
cp rootCA.pem assets/client/tls/ngrokroot.crt -f
# 拷贝服务器证书到指定目录,替换默认证书
cp server.crt assets/server/tls/snakeoil.crt -f
cp server.key assets/server/tls/snakeoil.key -f
这是使用了 cp 因为 直接使用cp,依然会提示是否需要覆盖,比较麻烦,使用 cp 强行覆盖,不提示
6. 编译服务器、客户端
sudo make release-server release-client
这个命令默认编译的是 linux 平台下 服务器、客户端。
linux服务器编译命令: sudo make release-server
我的客户端是win7,客户端需要交叉编译
[root@localhost ngrok]# GOOS=windows GOARCH=amd64 make release-client
生成的服务器可执行程序在 ./bin/ngrokd
生成的win7客户端可执行程序在 ./bin/windows_amd64/ngrok.exe
需要其他平台编译的参考下面:
不同平台使用不同的 GOOS 和 GOARCH,前面的编译选项就是指 go os , go 编译出来的操作系统 (windows,linux,darwin) ;go arch, 对应的构架 (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
不同平台命令后跟上 make release-client / make release-server 就行编译指定平台 client / server
编译使用的go包说明:
- go-bindata 包,该库是一套将任意资源文件转成二进制数据反向生成到Go代码供hash调用的技术,Ngrok的源码利用这一技术将公网证书和密钥,以及站点的HTML生成到go代码中去了,使其变成了一堆byte数组,在程序中hash调用。这么做固然有它的好处,但缺点也显而易见,因为这套技术要提前用一个项目的程序生成另一个项目的Go代码,所以编译起来难免繁琐,于是Ngrok提供了makefile文件以供用户make编译,这就有点尴尬了,本来好好的跨平台Go语言项目,被make和makefile活生生憋成了只能Linux使用的了。
- build -tags 技术,通过Ngrok项目,我第一次知道Go的这个特性,可以在代码顶端加上
// +build !release
等标记,注明编译时的模式,比如前面这种表达方式,就是在非release编译模式下才会编译这个文件,然后使用go build -tags 'release'
或者go build -tags 'debug'
来控制是否编译这个代码文件。这个特性确实灵活,可以在项目中编写不同的编译模式下的代码,缺点呢,就是没有详细文档的情况下,第三方用户并不知道有哪些编译模式,加大了源码本地编译的复杂度,所以这也是原版Ngrok项目使用makefile文件的原因之一。 - equinox.io 技术,这项技术可以让Go代码在编译和运行期间保持更新,代码作者更新代码后,能够在第三方用户实时更新,具体没有了解,我看原版Ngrok在进行release编译时增加了很多equinox.io令牌密钥,以连接远程仓库,保证代码更新。
7. 下载客户端 执行程序到客户端执行环境
sz ./bin/windows_amd64/ngrok.exe
注: sz 命令需要安装 yum install -y lrzsz
此处有个坑,如果只下载 客户端执行文件是不行的。还需要把第5个步骤中的
assets/client/tls/ngrokroot.crt 一并下载并覆盖到客户端执行环境下,提示,最好是把 assets 这个目录打包压缩,下载到客户端解压,给client使用。
客户端需要ngrok.exe ngrok.cfg 以及 assets 目录,直接把服务器端 覆盖过证书的这个目录 assets 也下载到客户端环境,执行程序同一级目录即可。
下面是客户端目录主要文件列表:
--- ngrok.exe
--- ngrok.cfg
--- assets
--- --- client
--- --- --- tls
--- --- --- --- ngrokroot.crt
8. 执行 服务端
[root@localhost ngrok]# ./bin/ngrokd -tlsKey=./server.key -tlsCrt=./server.crt -domain="dev.mydomain.com" -httpAddr=":80" -httpsAddr=":443" -tunnelAddr=":4443"
[15:09:40 CST 2018/10/26] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [registry] [tun] No affinity cache specified
[15:09:40 CST 2018/10/26] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [metrics] Reporting every 30 seconds
[15:09:40 CST 2018/10/26] [INFO] (ngrok/log.Info:112) Listening for public http connections on [::]:80
[15:09:40 CST 2018/10/26] [INFO] (ngrok/log.Info:112) Listening for public https connections on [::]:443
[15:09:40 CST 2018/10/26] [INFO] (ngrok/log.Info:112) Listening for control and proxy connections on [::]:4443
服务端参数解析:
a. 可以看到 侦听 80 443 4443
b. ngrok客户端连接的是客户端配置文件:ngrok.cfg 内配置的端口 4443
server_addr: "dev.mydomain.com:4443"
c. -domain
为你的服务域名,-httpAddr
为http服务端口地址,访问形式为xxx.
dev.mydomain.com:
4443,也可设置为80默认端口,-httpsAddr
为https服务,同上。
ngrokd还会开一个端口用来跟客户端通讯(可通过-tunnelAddr=":xxx"
指定),如果你配置了 iptables 规则,需要放行这个通讯端口(4443)上的 TCP 协议。
firewall-cmd --zone=public --add-port=4443/tcp --permanent
firewall-cmd --reload
9. 启动客户端
此处客户端配置文件是个大坑,按照网上大量分享的配置
server_addr:"dev.mydomain.com:4443"
trust_host_root_certs:false
类似这种配置完全不行,各种问题,原因是网上大家分享的是最新版本ngrok的配置。
而我们编译的是开源版本 2.1.7 版本,是较旧版本,需要配置按照yaml方式设置
server_addr: "dev.mydomain.com:4443"
trust_host_root_certs: false
tunnels:
abc:
proto:
http: 8081
subdomain: ngrok
这配置也是个坑。。里面不许用tab,只能用空格, 不然客户端就启动失败。
10. 连接成功
客户端 cmd 命令行
C:ngrok>.ngrok.exe -config=ngrok.cfg -log=out.log -subdomain=abc 8081
这个子域名 subdomain=abc 作用是,最终生成的映射域名是 abc.dev.mydomain.com
客户端启动一个http服务,端口8081。此客户端是需要被映射到ngrok上,提供给别人访问的服务。
如果跟ngrok连接success,ngrok客户端会输出下图内容:
隧道状态绿色字体: online 即为成功。
此时,浏览器输入 http://abc.dev.mydomain.com/ 可以测试验证,
如果想实现其他局域网内终端访问该内网http服务, 则需要,其他网络内的终端,把本机dns 设置下,
C:windowsSystem32driversetchosts
文件内需要新增dns解析记录 10.8.0.1 abc.dev.mydomain.com
10.8.0.1 即为 ngrok server 服务器IP地址。
11. ngrok启动后,内部会提供一个http服务,浏览器内输入http://localhost:4040/http/in
就可以查看,当前状态
12. 还有个大坑!
证书重新生成后,居然客户端/服务器可执行程序,需要重新编译。
否则会输出
Failed to read message: remote error: bad certificate
先写这么多,回头继续。
最后
以上就是俊秀雪碧为你收集整理的ngrok使用/踩坑分析-http代理的全部内容,希望文章能够帮你解决ngrok使用/踩坑分析-http代理所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复