目前,公网 IP 地址数量稀少,我们的个人电脑大都在重重内网内部,端口号通过 NAT 层层映射,导致无法向公网提供一个稳定的访问入口。若想让公网提供服务(比如搭建一个的Web服务器)我们一般选择购买云服务器,但是性能强大的云服务器价格很高,因此我们应该找一个办法让内网的电脑能向公网暴露一个 稳定的 访问入口。

  ngrok 就能用来解决这个问题。

ngrok 原理

   ngrok 的原理很简单,总结起来就是 tcp 数据转发。ngrok server端 运行在一台公网能访问的服务器上,client 端运行在你想暴露给公网的内网电脑上,client端 和 server端保持tcp连接,server端监听请求。当某个请求到达 server端后,server端将请求内容通过保持的 tcp链接 转发到client端,然后client端再去请求你运行在内网电脑上的服务,并把请求结果通过这个通道反向传递回去。这样通过一层代理就完成了内网穿透。

  所以我们搭建 ngrok 前,可以准备这些东西:云服务器(性能可以差一点)域名(也可以不要)

搭建 ngrok

编译

  ngrok 是使用 go 语言开发的,编译需要准备 golang 环境,此外还需要 git,make。

  从 GitHub 获取 ngork 代码,然后在目录下执行 make all,生成 ngrokdngrok

  可能遇到 bin/go-bindata 找不到的问题,执行 go get github.com/jteeuwen/go-bindata/go-bindata ,然后看看 go-bindata 文件被放在哪个目录了,一般是你 golang 安装目录的 bin 文件夹。然后修改一下 Makefile,修改下面两个中 go-bindata 的路径,然后再 make all

client-assets:
 你的go-bindata路径 -nomemcopy -pkg=assets -tags=$(BUILDTAGS) \
  -debug=$(if $(findstring debug,$(BUILDTAGS)),true,false) \
  -o=src/ngrok/client/assets/assets_$(BUILDTAGS).go \
  assets/client/...

server-assets:
 你的go-bindata路径 -nomemcopy -pkg=assets -tags=$(BUILDTAGS) \
  -debug=$(if $(findstring debug,$(BUILDTAGS)),true,false) \
  -o=src/ngrok/server/assets/assets_$(BUILDTAGS).go \
  assets/server/...

服务端配置

  服务端参数如下:

  -domain string
     用哪个域名来访问你内网的电脑,比如:xxx.com。(你得有这个域名,且DNS解析到这个服务器的ip)
  -httpAddr string
     监听 http 请求的端口,如: ":80"
  -httpsAddr string
     监听 https 请求的端口,如: ":443"
  -log string
     输出日志文件路径,默认打印到标准输出。
  -log-level string
     输出日志文件等级,有 DEBUG, INFO, WARNING, ERROR (默认 "DEBUG")
  -tlsCrt string
     若要 ssl 加密传输,这个参数跟证书路径
  -tlsKey string
     若要 ssl 加密传输,这个参数跟密钥
  -tunnelAddr string
     监听client端的端口号,默认 ”:4443“

  若我想用 testtest.com 域名访问内网电脑,6666作为http端口,7777作为https端口,用端口5555和客户端通信,则启动参数为:

./ngrokd -domain="testtest.com" -httpAddr=":6666" -httpsAddr=":7777" -tunnelAddr=":5555"

  因为要一直运行在服务器上,你可以加上 setsid 将它放到后台 ( Linux系统 ),即:setsid ./ngrokd 参数。若想要开机自动启动该程序,可以把这条指令写成 shell 脚本,然后做成开机自动运行。CentOS 可以参考这篇博客:centos7之添加开机启动服务/脚本

客户端配置

  不要去官网(https://ngrok.com/)下载它那个 ngrok,它那个是收费版本,主要用来连接官方提供的 ngrok 服务器。使用我们上面编译的 ngrok 客户端。

  客户端参数如下:

  -authtoken string
     连接官网 ngork 服务器的认证token
  -config string
     ngrok配置文件路径
  -hostname string
     ngork 服务端地址
  -httpauth string
     认证:username:password
  -log string
     输出日志文件路径
  -log-level string
     输出日志文件等级,有 DEBUG, INFO, WARNING, ERROR (默认 "DEBUG")
  -proto string
     协议包括 'http', 'https', 'tcp' 默认:"http+https"
  -subdomain string
     子域名。比如,你服务端的domain配置的 testtest.com,这里的subdomain是 blog,那么访问的域名就是 blog.testtest.com

  ngrok的配置文件( xxx.cfg )一般包含这两项:

server_addr: "你的服务端地址:端口号(服务端的tunnelAddr)"
# 如果服务端配置了证书和密钥,这个表示不检查证书的合法性
# 如果你的证书是自己签的,那就 false,如果你有合法证书那就 true
trust_host_root_certs: false  

  客户端的启动命令示例:./ngrok -config=配置文件路径 8080 这里面的 8080 表示客户端应该向内网的哪个端口去请求内容。

  如上所示,整个 ngrok 就搭建好啦,尽情享受吧。: )