基于 HTTP/2 的 WEB 内网穿透实现

网络 网络管理
HTTP/2 引入了二进制分帧层,将 HTTP/1.1 中的请求和响应拆成颗粒度更细的帧(frame),从而实现了优先级、流量控制和 Server Push 等功能;HTTP/2 在单条 TCP 连接上可以打开多个流,从而实现了多路复用;HTTP/2 使用静态字典、动态字典以及哈夫曼编码,对请求 / 响应头部进行压缩。总之,HTTP/2 从协议层面解决了 HTTP/1.1 的诸多问题。

HTTP/2 引入了二进制分帧层,将 HTTP/1.1 中的请求和响应拆成颗粒度更细的帧(frame),从而实现了优先级、流量控制和 Server Push 等功能;HTTP/2 在单条 TCP 连接上可以打开多个流,从而实现了多路复用;HTTP/2 使用静态字典、动态字典以及哈夫曼编码,对请求 / 响应头部进行压缩。总之,HTTP/2 从协议层面解决了 HTTP/1.1 的诸多问题。

在我之前写的文章里,我介绍了如何通过 ngrok 让内网 WEB 在其它网络环境中能够被访问。本文要实现的服务与 ngrok 类似,我把它称之为 Pangolin,中文是穿山甲的意思(名字来自于同事的类似项目,在此表示感谢)。Pangolin 客户端和服务端之间的报文转发,是用 node-http2 这个 Node.js 模块提供的 HTTP/2 服务来实现的。

Pangolin 的需求来自于本博客用户评论(via)。实际上,能实现类似功能的软件很多,有使用私有协议进行转发的,有使用 WebSocket 进行转发的。而我认为 HTTP/2 应该是个不错的选择,打算试一下。最终我花了一个小时实现了一个初步能用的版本,除开 node-http2,全部代码不超过 200 行。代码我放在了 github 上,有兴趣的同学可以玩一下。

下面简单介绍它的原理,我画了一张草图:

 基于 HTTP/2 的 WEB 内网穿透实现

最左侧是最终用来访问服务的浏览器,它可能位于公网,也可能位于其它内网;最右侧是实际提供 WEB 服务的 HTTP Server,它位于内网。显然,左侧浏览器没办法直接访问右侧 WEB 服务,只能借助公网节点作为桥梁。中间的 pangolin 服务端运行在公网节点上;Pangolin 客户端运行在与 WEB 服务同台机器或者同一网段内。

浏览器发起请求后,请求报文沿着绿色箭头从左到右流动,每个节点都相当于左侧相邻节点的 HTTP Server。***的问题出现在 Pangolin 服务端和客户端之间:客户端位于内网,正常情况下 Pangolin 服务端连不上客户端提供的 HTTP Server。

这个问题我用了一个取巧的办法解决:由于 Pangolin 服务端有公网 IP,可以开启 TCP Server,客户端可以通过 IP 和约定的端口与服务端建立 TCP 连接。那么只要稍微改造一下 node-http2 的代码,使它可以基于指定 socket 创建 HTTP/2 Server、发送 HTTP/2 Request,就可以打通所有节点了。这个问题解决后,左侧的请求可以顺利到达右侧,响应数据也可以沿着之前的连接逐级返回。

Pangolin 服务端和客户端内部之间使用 HTTP/2,可以大幅提高性能,降低程序复杂性;对外使用 HTTP/1.1,保证了与已有系统的兼容性。

为了实现内网穿透,Pangolin 需要做以下准备工作:

Pangolin 服务端开启 TCP Server;

Pangolin 客户端启动 TCP Client,与 Pangolin 服务端连接,得到 socket 长连接;

Pangolin 客户端基于这个 socket 连接,开启 HTTP/2 Server;

Pangolin 服务端开启 HTTP/1.1 Server,等待浏览器来访问;

实际的数据传输流程如下:

浏览器向 Pangolin 服务端发起请求(HTTP/1.1);

Pangolin 服务端基于已有 socket,向 Pangolin 客户端发起请求(HTTP/2);

Pangolin 客户端向内网 WEB 服务发起请求,得到响应(HTTP/1.1);

Pangolin 客户端基于已有 socket,将响应返回给 Pangolin 服务端(HTTP/2);

Pangolin 服务端将响应返回给浏览器(HTTP/1.1);

由于 Pangolin 客户端采用了 HTTP 转发,而不是 TCP 隧道,所以可以轻松实现 ngrok 那样的管理界面,用来查看完整的 Request/Response 信息。目前我还只是简单地打印了请求日志。

HTTP/2 协议本身并没有规定它必须基于 TLS 部署,没有安全层的 HTTP/2 被称之为 h2c(HTTP/2 Cleartext)。目前来看,所有浏览器都不打算支持 h2c。但如果一个系统的某些环节对安全没有那么高的要求,或者已经通过了其它方案确保了安全,部署 h2c 也是一个非常好的选择。现在很多 HTTP/2 工具和类库同时支持 h2 和 h2c,node-http2 也是如此。

实际上,我为了测试方便,在实现 pangolin 时也选择了 h2c。通过 Wireshark 抓包可以看出,HTTP/2 层下面直接就是 TCP 层:

 基于 HTTP/2 的 WEB 内网穿透实现

责任编辑:何妍 来源: Jerry Qu的小站
相关推荐

2024-04-30 09:10:55

HTTP2TCP内网

2020-10-15 08:52:36

Frp内网Web

2020-10-13 14:03:50

搭建ngrok服务

2020-09-03 08:03:52

内网穿透

2024-11-25 16:25:23

内网穿透网络协议

2024-10-12 20:56:19

ProxyChain

2019-06-12 09:02:20

2022-09-19 13:11:56

命令SSH内网穿透

2019-02-28 08:44:19

内网钉钉Web

2021-10-27 20:40:24

办公

2021-11-02 10:40:51

内网穿透代理工具Linux

2024-03-13 08:03:02

2015-09-15 10:40:26

HTTP2 WEB 性能优化

2015-09-15 10:46:29

2015-09-15 10:54:54

HTTP2 WEB 性能优化

2013-04-22 10:07:08

2022-02-17 13:46:15

SSH命令内网

2023-11-29 10:16:45

内网开源

2022-02-25 13:45:09

TailscaleHeadscaleLinux

2019-04-22 14:44:16

内网穿透反向代理分离
点赞
收藏

51CTO技术栈公众号