ngrok 开发者指南
组件
ngrok 项目由两个组件组成,ngrok 客户端(ngrok)和 ngrok 服务器(ngrokd)。
ngrok 客户端是更复杂的部分,因为它有用于显示保存的请求和响应的 UI。
编译
git clone git@github.com:inconshreveable/ngrok.git
cd ngrok && make
bin/ngrok [LOCAL PORT]
有一些 Makefile 目标仅用于编译客户端或服务器。
make client
make server
注意:您必须使用 Go 1.1+编译!您必须安装 Mercurial SCM。
编译发布版本
客户端和服务器都包含静态资源文件。
这些包括 TLS/SSL 证书和客户端 web 界面的 html/css/js。
发布版本将所有这些数据嵌入到二进制文件中,而调试版本则从文件系统读取这些文件。
您应该始终在调试版本上进行开发,以便在测试静态资产中的更改时不必重新编译。
有用于编译用于发布的客户端和服务器的 Makefile 目标:
make release-client
make release-server
make release-all
本地开发
我在 ngrok 上开发的策略是:
将以下行添加到 /etc/hosts:
127.0.0.1 ngrok.me
127.0.0.1 test.ngrok.me
使用以下选项运行 ngrokd:
./bin/ngrokd -domain ngrok.me
使用以下内容创建 ngrok 配置文件"debug.yml":
server_addr: ngrok.me:4443
tunnels:
test:
proto:
http: 8080
然后使用以下任一命令运行 ngrok:
./bin/ngrok -config=debug.yml -log=ngrok.log start test
./bin/ngrok -config=debug.yml -log=ngrok.log -subdomain=test 8080
这将使您设置一个 ngrok 客户端与一个 ngrok 服务器对话,所有这些都在您的本地控制下。快乐的黑客!
网络协议与隧道
在高水平上,ngrok 的隧道工程如下:
连接设置和身份验证
- 客户端启动到服务器的长期 TCP 连接,并通过该连接传递 JSON 指令消息。此连接称为 控制连接。
- 建立连接后,客户端发送一条带有身份验证和版本信息的 Auth 消息。
- 服务器验证客户端的 Auth 消息,并发送一条 AuthResp 消息,指示成功或失败。
隧道创建
- 然后,客户机可能会要求服务器通过发送 ReqTunnel 消息为其创建隧道。
- 当服务器收到 ReqTunnel 消息时,它将发送一条或多条 NewTunnel 消息,指示隧道创建成功或失败。
隧道连接
- 当服务器接收到新的公共连接时,它通过检查 HTTP 主机头(或 TCP 隧道的端口号)来定位适当的隧道。这种来自公共互联网的连接称为 Public Connection。
- 服务器通过控制连接向客户端发送一条 ReqProxy 消息。
- 客户端启动到服务器的新 TCP 连接,称为 Proxy Connection。
- 客户端通过代理连接发送 RegProxy 消息,以便服务器可以将其与控制连接关联 (因此它负责的隧道).
- 服务器通过代理连接发送带有连接元数据信息的 StartProxy 消息 (客户端 IP 和隧道的名称).
- 服务器开始将流量逐字节从公共连接复制到代理连接,反之亦然。
- 客户端打开与为该隧道配置的本地地址的连接。这称为 Private Connection 。
- 客户端开始将流量逐字节从代理连接复制到专用连接,反之亦然。
探测死隧道
- 为了确定隧道是否仍处于活动状态,客户端定期通过控制连接向服务器发送 Ping 消息,服务器用 Pong 消息进行回复。
- 当检测到隧道已死亡时,服务器将清除该隧道的所有状态,客户端将尝试重新连接并建立新的隧道。
Wire format
消息作为以下格式的 NetString 通过网络发送:
<message length><message payload>
消息长度作为 64 位小端整数发送。
Code
The definitions and shared protocol routines lives under src/ngrok/msg
src/ngrok/msg/msg.go
这里定义了所有不同的消息类型(Auth, AuthResp, ReqTunnel, RegProxy, StartProxy 等),并记录了它们的字段。这是一个了解客户机和服务器之间发送的消息的好地方。
ngrokd - 服务端
Code
服务器的代码位于 src/ngrok/server 下
Entry point
ngrokd 入口点位于 src/ngrok/server/main.go 中。
There is a stub at src/ngrok/main/ngrokd/ngrokd.go for the purposes of creating a properly named binary and being in its own “main” package to comply with go’s build system.
ngrok - 客户端
Code
客户端代码位于 src/ngrok/client 下
Entry point
ngrok 入口点位于 src/ngrok/client/main.go 中。
There is a stub at src/ngrok/main/ngrok/ngrok.go for the purposes of creating a properly named binary and being in its own “main” package to comply with go’s build system.
静态资源
ngrok web 界面的 html 和 javascript 代码以及其他静态资源(如 TLS/SSL 证书)位于顶级的 assets 目录下。
除此之外
更多文档可以在代码本身的注释中找到。