利用ngrok服务内网穿透-轻松调试本机站点
我们经常会有「把本机开发中的 web 项目给朋友看一下」这种临时需求,为此专门在 服务上部署一遍就有点太浪费了。
之前我通常是在 ADSL 路由器上配个端口映射让本机服务在外网可以访问,但现在大部分运营商不会轻易让你这么干了。一般小运营商也没有公网 IP,自己的路由器出口还是在局域网内,端口映射这种做法就不管用了。
之前我就想过能否借助拥有公网 IP 的主机中转来实现这种需求,后来发现已经有这样的软件了:ngrok。而且 ngrok 官网本身还提供了公共服务,只需要注册一个帐号,运行它的客户端,就可以快速把内网映射出去。
[ngrok官网](https://ngrok.com/)
我们现在是自己搭建ngrok服务端。前提条件是:一台外网可访问的主机,且有域名解析至该主机上。
ngrok是什么鬼?
如果你完全不知道它是什么东西,可以在它的github项目上了解下:https://github.com/inconshreveable/ngrok
这里只提下它的核心功能:能够将你本机的HTTP服务(站点)或TCP服务,通过部署有ngrok服务的外网伺服器暴露给外网访问!
如上封面图所示,举一个栗子。
- 橘色屏幕的笔记本是你的工作机器,安装了ngrok客户端
- ngrok.com所在的服务器安装了ngrok的服务端(ngrokd)
- 利用ngrok 8080命令可以将你本机的8080端口暴露给反向代理至ngrok.com的某个二级域名如:xxx.ngrok.com
- 别人通过xxx.ngrok.com就可以访问你本机8080端口上的站点内容了。
由此可见,除了Weinre、browsersync 这些惯用的手段外,借助ngrok,也一样可以解决前端开发过程经常遇到的“本地开发,外网调试”老大难题。
搭建服务端ngrokd
1.安装go语言开发环境
ngrok是利用go语言开发的,所以先要在服务器上安装go语言开发环境。
以CentOS的服务器示例,安装Go语言很简单的:
1 | sudo yum install golang |
安装完毕后,利用go version来验证是否安装成功。
go安装好后,我们再设置下go的环境变量:
在~/.zshrc
或~/.bash_profile
文件内,加入以下环境变量配置内容:
1 | export GOPATH=$HOME/go |
保存后,重新给shell加载下配置文件:source ~/.zshrc
。当然这一步可以省略。
最后可通过go env查看是否配置成功。
2.安装git
安装过程略。后面我们需要利用git拉取源码。
3.fork并拉取ngrok的源码
下面编译过程需要改官方的部分源码,所以最好fork一份源码至自己的github账户。
1 | $ mkdir -p ~/go/src/github.com/mamboer |
在编译ngrok的源码之前,我们还需要改下官方源码用到的签名证书。
4.生成自签名证书
使用ngrok.com官方服务时,我们使用的是官方的SSL证书。自建ngrokd服务,如果不想买SSL证书,我们需要生成自己的自签名证书,并编译一个携带该证书的ngrok客户端。
证书生成过程需要一个NGROK_BASE_DOMAIN。 以ngrok官方随机生成的地址693c358d.ngrok.com为例,其NGROK_BASE_DOMAIN就是”ngrok.com”,如果你要 提供服务的地址为”example.ngrok.xxx.com”,那NGROK_BASE_DOMAIN就应该 是”ngrok.xxx.com”。
我们这里以NGROK_BASE_DOMAIN=“ngrok.pangxieke.com”为例,生成证书的命令如下:
1 | $ cd ngrok |
执行完以上命令,在ngrok目录下就会新生成6个文件:
1 | -rw-rw-r-- 1 lv lv 985 Feb 17 19:04 device.crt |
ngrok通过bindata将ngrok源码目录下的assets目录(资源文件)打包到可执行文件(ngrokd和ngrok)中 去,assets/client/tls和assets/server/tls下分别存放着用于ngrok和ngrokd的默认证书文件,我们需要将它们替换成我们自己生成的:(因此这一步务必放在编译可执行文件之前)
1 | cp rootCA.pem assets/client/tls/ngrokroot.crt |
5.编译客户端程序ngrok和服务端程序ngrokd
在ngrok目录下执行如下命令,编译ngrokd:
1 | $ make release-server |
这时候会产生ngrokd文件。
我们可以将ngrokd文件拷贝至~/go/bin
目录下,以方便在其他目录内也可以直接通过ngrokd来访问该执行程序。
6.运行ngrokd服务
运行刚才生成的ngrokd文件
1 | ngrokd -domain="ngrok.pangxieke.com" -httpAddr=":8088" -httpsAddr=":8089" |
这时候会有相应提示信息:
1 | [15:08:52 CST 2016/02/18] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [registry] [tun] No affinity cache specified |
7.添加dns解析
在自己DNS服务器上,添加两条A记录:ngrok.fex.im
和*.ngrok.fex.im
,指向自己服务器ip。
8.防火墙开发端口
开放相应端口
1 | -A INPUT -p tcp -m state --state NEW -m tcp --dport 4443 -j ACCEPT |
1 | # 重启 |
至此为止,我们的ngrokd服务端搭建配置完成。
搭建ngrok客户端
我们可以在CentOS系统的服务器上编译了一份客户端的执行程序-一个ngrok文件。
如果你的开发机器系统也是CentOS,是可以直接将ngrok这个客户端执行文件拷贝到本地开发机器中来使用的。
但如果你的机器是Mac 或者windows,我们还需要在自己的电脑中编译一份相同签名文件的客户端程序!
类似的,利用以下命令编译ngrok:
1 | $ make release-client |
成功编译后,会在bin目录下找到ngrok
这两个文件。
如果是Mac作为客户端,编译:
1 | sudo GOOS=darwin GOARCH=amd64 make release-server release-client |
这样在 ngrok/bin 目录下会多出来一个 darwin_amd64 目录,这里的 ngrok 文件就可以拷到 Mac 系统用了。
服务器是CentOS,自己的工作电脑是Mac,所以得在自己的电脑中编译一份相同签名文件的客户端程序!
当然我们可以用源码在本机编译一份。或者使用Docker镜像编译。
服务验证
ngrokd服务配置好了,客户端程序也有了,下面测试下ngrok是否能够正常使用。
1.创建一个ngrok配置文件:ngrok.cfg
1 | server_addr: "ngrok.pangxieke.com:4443" |
2.运行客户端,暴露8080端口的站点
1 | ngrok -subdomain demo -config=./bin/ngrok.cfg 8080 |
3. 终端会出现如下信息,如果线上online代表链接成功。
如果如下,其实并未成功
4. 在8080端口下建一个测试站点
方便起见,我们拉取git@github.com:o2team/brand.git做测试:
1 | npm i -g node-static |
5. 在浏览器中查看
输入demo.ngrok.pangxieke.com:8088, 查看是否成功响应。
6. 查看请求状况。
ngrok客户端开放了本机4040端口,提供了一个web页面,我们在浏览器中输入:localhost:4040,可以查看到相关信息。
注意事项
客户端ngrok.cfg中server_addr后的值必须严格与-domain以及证书中的NGROK_BASE_DOMAIN
相同,否则Server端就会出现如下错误日志:
1 | [03/13/15 09:55:46] [INFO] [tun:15dd7522] New connection from 54.149.100.42:38252 |
注意开放服务端相关端口。
Docker搭建
docker build服务端及客户端
我们可以利用hteen/ngrok
镜像来搭建。生成客户端和服务端
1 | docker run --rm -it -e DOMAIN="ngrok.pangxieke.com" -v /data/docker/services/ngrok:/myfiles hteen/ngrok sh /build.sh |
build成功会有相应提示
此时会在本机/data/docker/services/ngrok
生成下列文件
1 | base.key base.pem base.srl bin device.crt device.csr device.key |
bin
目录下有服务端和客户端文件。这时候启动相关服务就可以了。
服务端使用docker启动
将刚才``/data/docker/services/ngrok目录下生成的配置文件复制到服务器,放在
/data/services/ngrok/config`
1 | docker run -idt --name ngrok-server \ |
参考文章https://www.jianshu.com/p/dff09c0124c2