ngrok 简介及作用

ngrok 是一款用 go 语言开发的开源软件,它是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。

server 环境配置

  • git 上下载

  • 生成证书

  • 生成服务器版本 server 上安装的 ngrokd

  • 生成各个平台上的 client 上安装的 ngrok

调试

有一些要点要特别注意,我就是在这些东西上面绕了很久,配置的时候需要特别注意的地方:

防火墙设置:

服务器和客户端都要关闭对应端口的防火墙,否则不能链接会一直显示 connecting

证书一定要设置正确:

证书会被编译到可执行文件中去,所以设置的时候需要正确设置地址,如果设置错误,最好是重新 git clone 一份代码来配置,make clean 在这里面似乎不能清除原有的配置。
交叉编译的时候要注意平台是 32 位系统(386)、64 位系统(amd64)或者 arm ,设置错了不能运行

server 配置

首先要安装 server 必须要的软件, 因为现在的阿里云自己的镜像带了 rhel 的源,所以可以直接偷懒用 yum 安装所有的东西。

git 下载

我安装的时候用的 root, 所以比较偷懒的在目录 /root/ 下配置

1
cd /root

官方地址,可能会报错,最近应该已经修复

git clone https://github.com/inconshreveable/ngrok.git

证书生成

在使用官方服务的时候,我们使用的是官方的 SSL 证书,所以如果直接编译的话,默认的链接地址会到官方的 ngrok.com 去,所以我们需要自己生成证书。 证书非常关键,所有编译的文件都会携带证书文件在程序内部 所以证书生成的时候要保证所有的地方都是对应的。

首先我们要确定我们要使用的地址,这是受到域名解析服务的影响的。最简单的办法就是 ping 一下这个地址看是不是能够获得自己的服务器 ip 。这个服务一定是架设在当前的服务器上的,所以 dns 一定是 ping 了之后指向当前的服务器。

我使用的域名是 www.example.com , ip 地址就是我自己的服务器。最好先 ping 一下确定一下,有一些 dns 没有绑定,会导致不能访问;如果更换域名,又需要重新来一遍全过程,非常繁琐。所以一定要先确定好。

当域名为 www.example.com 的时候,最终效果是远程机器的设置子域名为 abc 时,访问 abc.www.example.com: 端口 就可以。端口是由运行的时候配置的,并不需要确定某一个端口,都是可以设置的。

大概的原理和效果讲清楚之后就开始写怎么做了:

1
cd /root/ngrok

这里修改为自己的域名

1
2
3
4
5
6
7
NGROK_DOMAIN="www.example.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 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

首先进入到 ngrok 的目录,然后设定域名地址,这里需要修改为自己的。openssl 就是生成 SSL 证书文件的过程,之后会在 ngrok 目录下生成 root,device 等六个文件。 然后需要拷贝到配置的目录中,在编译的时候会使用这些文件。

1
2
3
cp -r rootCA.pem assets/client/tls/ngrokroot.crt 
cp -r device.crt assets/server/tls/snakeoil.crt
cp -r device.key assets/server/tls/snakeoil.key

生成服务器的 ngrokd

前面的配置工作已经完成,后面的就比较简单轻松了。由于是 go 语言写的,所以使用 golang 的 make 选项就好。

1
2
cd /root/ngrok
make release-server

等待下载和构建,如果下载失败什么的,估计是因为链接国外的服务器会断线的问题,重新运行一遍 make release-server 就好。

构建完成以后可以在 bin 目录下看到 ngrokd 这个文件,这个就是我们后面要开启的服务器端,现在先不要运行。

编译客户端的 ngrok

这里我们需要交叉编译,使用不同的编译选项来选择编译以后生成的平台

这里我主要是生成了 windows 、 arm 和 Linux 的版本。继续在原先的目录下:

1
2
3
GOOS=linux GOARCH=amd64 make release-client
GOOS=windows GOARCH=amd64 make release-client
GOOS=linux GOARCH=arm make release-client

不同平台使用不同的 GOOS 和 GOARCH,前面的编译选项就是指 go os , go 编译出来的操作系统 (windows,linux,darwin) ;go arch, 对应的构架 (386,amd64,arm)

1
2
3
4
5
6
7
8
9
10
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

通过前面的步骤,就会在bin目录里面生成所有的客户端文件,客户端平台是文件夹的名字,客户端放在对应的目录下,当前Linux平台客户端在bin目录下。然后我们就可以打个包,把所有文件下载到自己的本机了。

1
2
cd /root/ngrok
zip -r bin/

然后生成了Bin.zip的文件,通过scp之类的工具下载。

这个里面的注意

服务端叫 ngrokd

客户端叫 ngrok

所以以后要放到对应的平台,就只需要对应平台里面的ngrok文件就可以了。

配置服务器

在server端直接执行就可以了,其中NGROK_DOMAIN对应的就是一开始设置过的域名地址。

但是有一点要重点注意,就是httpAddr等端口的设置。

httpAddr 是访问普通的http使用的端口号,用后面用 子域名.www.aiesst.com:6060 来访问服务

httpsAddr 是访问的https使用的端口号,同上,只不过是需要https的服务访问才用这个端口

tunnelAddr 是通道的端口号,这个端口是Ngrok用来通信的,所以这个端口在服务器上和客户端上设置必须要对应才可以正常的链接,默认不填写好像是4433

1
2
3
4
5
6
cd /root/ngrok
NGROK_DOMAIN="www.aiesst.com"
#http,https,tcp, 注意:如果不需要http/https支持,可以直接类似-httpAddr=""来表示
bin/ngrokd -domain="$NGROK_DOMAIN" -httpAddr=":6060" -httpsAddr=":6061" -tunnelAddr=":6062"
#https设置了tls
#bin/ngrokd -domain="www.aiesst.com" -httpAddr=":6060" -httpsAddr=":6061" -tunnelAddr=":6062" -tlsKey=./device.key -tlsCrt=./device.crt

验证端口是否打开的问题

当打开了服务端程序之后,如果有疑问可以测试一下,因为有时候可能会遇到这个问题。我在一开始的时候并没有注意到防火墙问题,所以一直导致不能成功。除了这个问题之外,使用阿里云还有一些问题,就是我使用的系统是CentOS,默认是没有打开对应的端口的,如果遇到这个问题需要先验证一下端口是否打开。我使用了工具nc来测试。

使用的命令是:

1
nc -v -w 10 -z 127.0.0.1 6060-6062

如果显示的3个端口都有响应(都显示了 succeeded 就是正常),那么就可以继续开始后面的步骤。

打开防火墙

如果是centOS的系统,防火墙应该是 firewall-cmd 来控制。对应的命令就是,其中端口号要写自己的:

1
2
firewall-cmd --permanent --zone=public --add-port=6060-6062/tcp  //永久
#firewall-cmd --zone=public --add-port=6060-6062/tcp //临时

如果是ubuntu之类的系统,防火墙一般是iptables来控制,对应的命令就是,也要修改自己的端口号才可以:

1
2
iptables -A INPUT -p tcp --dport 6060-6062 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 6060-6062 -j ACCEPT

打开了服务器的端口,然后就可以继续配置客户端。

配置windows客户端

这里的客户端就是指另外一台电脑,这一台电脑可以链接到服务器的电脑上,客户端常常是我们内网的电脑,这个就是ngrok实现的最大意义,可以和在公网的服务器通信之后,再直接访问内网电脑提供的服务,实现内网穿透。

这里我先使用了windows来测试,因为平时用的系统,有各种工具,相对会比较方便。

先找到一开始通过 scp 下载的 Bin.zip 文件,解压到任意目录。然后找到window版本的客户端 ngrok.exe。复制到任意目录,自己方便操作就好。我使用了 D:\tmp\ 文件夹

先在这个目录下建立一个文件 ngrok.cfg ,然后写入内容:

地址和服务器设置的 NGROK_DOMAIN=”www.aiesst.com” 中的地址保持一致
端口和服务器设置的通道端口 tunnelAddr=”:6062” 保持一致

1
2
server_addr: "www.aiesst.com:6062"
trust_host_root_certs: false

然后 ctrl-r 打开运行,运行 cmd,输入:

日志: -log=ngrok_log.txt 是记录ngrok的日志,如果前期调试的时候加上这个参数,如果不能访问就可以查看到底是什么问题

子域名: -subdomain=abc 是定义访问的时候的子域名,现在访问

abc.www.aiesst.com:6060 就可以访问到这一台机器上80端口的服务

1
2
3
D:
cd tmp
ngrok.exe -log=ngrok_log.txt -subdomain=abc -config="ngrok.cfg" 80

稍微等待5秒钟,如果看到显示有 tunnel status: online ,那么后面的 forwarding 对应的内容就是访问本机的地址。

当然在windows上面,你需要再跑一个其他的服务在80端口可以看到访问的效果。

总之就是如果显示了 tunnel status: online 就是服务器和客户端是正常链接的,通过浏览器访问 abc.www.aiesst.com:6060 就可以链接到现在的内网主机上的服务。

TCP转发

这里以转发ssh为例,重新改写客户端配置文件ngrok.cfg

1
2
3
4
5
6
7
8
9
10
11
server_addr: ngrok.sfantree.com:4443
trust_host_root_certs: false
tunnels:
http:
proto:
http: 80
subdomain: pi
ssh:
remote_port: 10086
proto:
tcp: 22

这里我把需要转发的http和ssh都写入配置文件,其他tcp服务语法格式和ssh相似,remote_port为远程端口,等下外网连接的时候用的就是这个remote_port,tcp:22为需要转发的本地端口。

1
./ngrok-for-arm -config=ngrok.cfg start http ssh

重新运行客户端,start指明需要的服务类型,建议开一个screen。

ssh popy32@ngrok.sfantree.com -p 10086
连接时指明远程端口

总结

从Ngrok强大的反向代理功能可以看出Go语言独特魅力,除了glibc的版本有一定要求,其跨平台编译为部署省去了不少时间,当然Go还有更多的优点,本文提到的也只是Ngrok的冰山一角,利用其TCP转发也可以远程SSH树莓派,更多玩法就自行百谷了。

来源:https://blog.csdn.net/y_xianjun/article/details/73194622

注意:使用Vue开发时候,调试时候会报“Invalid Host Header”, 工程需要在webpack.dev.conf.js文件的devServer字段设置disableHostCheck: true才能允许代理访问