HTTP2 ERR CONNECTION CLOSED(开销太大)

HTTP2 ERR CONNECTION CLOSED (Too much overhead)

我们正在开发一个项目,前端使用 Angular,后端使用 Spring。没什么新鲜的。但是我们已经将后端设置为使用 HTTP2,但有时我们会发现奇怪的问题。

今天我从 chrome 开始玩 "Network Log Export",我在日志的 HTTP2_SESSION 行中发现了这条有趣的信息。

t=43659 [st=41415]    HTTP2_SESSION_RECV_GOAWAY
                  --> active_streams = 4
                  --> debug_data = "Connection [263], Too much overhead so the connection will be closed"
                  --> error_code = "11 (ENHANCE_YOUR_CALM)"
                  --> last_accepted_stream_id = 77
                  --> unclaimed_streams = 0
t=43659 [st=41415]    HTTP2_SESSION_CLOSE
                  --> description = "Connection closed"
                  --> net_error = -100 (ERR_CONNECTION_CLOSED)
t=43661 [st=41417]    HTTP2_SESSION_POOL_REMOVE_SESSION
t=43661 [st=41417] -HTTP2_SESSION

看来 ERR_CONNECTION_CLOSED 问题的根源是服务器认为来自同一客户端的开销过多并关闭了连接。

问题是 ¿我们能否调整服务器以接受达到一定限度的开销?如何?我相信这是我们应该能够在 Spring 或 tomcat 或那里的某个地方进行调整的东西。

干杯 伊格纳西奥

针对 2019 年年中针对 HTTP/2 的 collection of CVE's 报告,实施了开销保护。虽然 Tomcat 没有受到直接影响(恶意输入没有'触发过载)我们确实采取了措施来阻止与恶意配置文件匹配的输入。

从你的 GitHub comment, you see issues with POSTs. That strongly suggests that the client is sending the POST data in multiple small packets rather than a smaller number of larger packets. Some clients (e.g. Chrome) 知道偶尔这样做是因为他们缓冲数据的方式。

许多 HTTP/2 DoS 攻击可以概括为发送比数据更多的开销。虽然 Tomcat 没有受到直接影响,但我们决定监控以这种方式运行的客户端,如果发现任何客户端可能是恶意的,则断开连接。

通常,数据包会减少开销计数,非数据包会增加开销计数,而(可能)恶意数据包会显着增加开销计数。这个想法是,一个已建立的、通常表现良好的连接应该能够在偶尔的 'suspect' 数据包中幸存下来,但超过这个数会迅速触发连接关闭。

就小 POST 数据包而言,关键 configuration setting 是:

  • overheadCountFactor
  • overheadDataThreshold

开销计数从 -10 开始。对于接收到的每个数据帧,它减少 1。对于每个设置、优先级和 PING 帧,它增加 overheadCountFactor。如果开销计数超过 0,连接将关闭。

此外,如果接收到的非最终数据帧和先前接收到的数据帧(在同一流上)的平均大小小于 overheadDataThreshold,则开销计数增加 overheadDataThreshold/(average size of current and previous DATA frames).这样,DATA帧越小,开销增加越大。少量非最终数据帧应该足以触发连接关闭。

存在平均值,因此 Chrome 所展示的缓冲不会触发开销保护。

要诊断此问题,您需要查看日志以了解客户端发送的非最终数据帧的大小。我怀疑这会显示一系列大小小于 1024(overheadDataThreshold 的默认值)的非最终数据帧。

要解决此问题,我的建议是先查看客户端。为什么它会发送小的非最终数据帧,如何才能阻止它?

如果您需要立即缓解,则可以减少 overheadDataThreshold。您获得的有关客户端发送的 DATA 帧大小的信息应该指导您将其设置为什么。它需要小于客户端发送的数据帧。在极端情况下,您可以将 overheadDataThreshold 设置为零以禁用保护。