首页 > 解决方案 > 为 HTTP/2 代理实现 websocket 支持

问题描述

我正在开发这里提到的 https http/2 代理服务器: https ://chromium.googlesource.com/chromium/src/+/HEAD/net/docs/proxy.md#HTTPS-proxy-scheme 那里提到

由于更高的连接限制(Chrome 中的 HTTP/1.1 代理被限制为跨所有域的 32 个同时连接),使用 HTTP/2 的 HTTPS 代理在 Chrome 中可以提供比常规 HTTP 代理更好的性能。

但是,当用户尝试通过原始 http 连接浏览使用 websocket 的网站时,响应包含“升级”http 标头,该标头禁止在 http/2 中使用,因为没有用于 HTTP/2 的 websocket。 https://daniel.haxx.se/blog/2016/06/15/no-websockets-over-http2/#:~:text=There%20is%20no%20websockets%20for%20HTTP%2F2.&text=That% 20spec%20details%20how%20a,connection%20into%20a%20websockets%20connection。 问题在于,当 http1.1 流量通过实现 http/2 的 https 代理时,标头必须从 http1.1 传输到 http/2。当然,当网页使用 TLS 时,不存在所有流量通过 http 'CONNECT' 方法建立的连接这样的问题。当网站不使用 TLS 时会出现问题。如果没有解决这个问题,说明 HTTPS 代理不应该实现 HTTP/2 协议。

标签: websocketproxyhttp2

解决方案


因为没有用于 HTTP/2 的 websocket

您发布的链接是旧的,从那时起,通过 HTTP/2 的 WebSocket 已由RFC 8441指定。

HTTP/2 代理的行为在RFC 7540 第 8.3 节中指定。

当客户端使用安全的 HTTP/2 与代理通信时,每个 HTTP/2 流都是通往服务器的“隧道”。

客户端和代理使用安全的 HTTP/2 进行通信,并且发生“隧道”是因为每个 HTTP/2 流都成为具有“无限”响应的“无限”请求,即DATA双向的“无限”系列 HTTP/2 帧携带不透明的字节数组有效载荷。

代理的工作是解包DATA客户端收到的帧,并将字节数组有效负载转发给服务器,DATA如果代理和服务器之间的通信也是 HTTP/2(它可能可以优化解包和重新包装,但这可能很棘手——例如流编号可能不同)。

当客户端尝试通过 HTTP/2 执行 WebSocket 时,浏览器将按照 RFC 8441 的规定进行操作,并且代理将接收CONNECT带有:protocol伪标头的请求,并且代理必须知道在这种情况下要做什么,具体取决于它使用什么协议与服务器通信。

以上描述了当与客户端的通信是 HTTP/2 时您的代理需要支持的内容。

如果您的代理需要支持使用 HTTP/1.1 的客户端,那么您需要实现代理支持 HTTP/1.1 和 WebSocket 代理所需的功能,这通常并不难:第一个只是 HTTP/1.1 转发或 HTTP CONNECT"隧道”,第二个是 WebSocket HTTP 升级请求转发,然后是“隧道”连接,甚至是成熟的 WebSocket 代理。

免责声明,我已经在J​​etty Project中实现了上述所有内容。您可以使用 Jetty 10 或更高版本来实现 HTTP/1.1、HTTP/2 或 WebSocket,客户端和服务器(因此也是代理)。也支持基于 HTTP/2 的 WebSocket。

最后,要回答您的最后一个问题,即使存在 WebSocket,也完全有可能让安全代理支持 HTTP/2。

例如,与服务器的明文 WebSocket 连接以 HTTP 升级请求开始;该请求将被加密发送到代理,代理将对其进行解密并将其转发到服务器(使用服务器支持的任何协议——甚至可以是基于安全 HTTP/2 的 WebSocket);服务器将回复 101 并将连接升级到 WebSocket;代理将从服务器接收 101 并升级到“隧道”或 WebSocket 代理;代理加密 101 响应并将其转发给客户端;客户端解密它并升级到 WebSocket 的连接。此时,客户端通过与代理的安全连接向服务器发送明文 W​​ebSocket (代理看到明文 WebSocket 通信)。

CONNECT反之亦然,与服务器的安全 WebSocket 连接从通过代理到服务器建立 HTTP 隧道开始;然后客户端将与服务器建立安全通信;然后它将 HTTP 升级到 WebSocket 发送到服务器(通过代理隧道)。此时,客户端正在通过与代理的安全连接向服务器发送安全的 WebSocket(代理无法看到 WebSocket 通信)。

HTTP/2 变体类似,只是考虑了 HTTP/2 特定的“隧道”和传输 WebSocket 的方式。


推荐阅读