HTTP2 ERR 连接已关闭(开销太大)

Ign*_*oHR 5 tomcat google-chrome overhead spring-boot http2

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

\n\n

今天我开始使用 chrome 中的“网络日志导出”,我在日志的 HTTP2_SESSION 行中发现了这条有趣的信息。

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

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

\n\n

问题是\xc2\xbf我们可以调整服务器以接受一定限度的开销吗?\xc2\xbf怎么办?我相信这是我们应该能够在 Spring 或 tomcat 或其他地方进行调整的东西。

\n\n

干杯\n伊格纳西奥

\n

Mar*_*mas 6

实施开销保护是为了响应2019 年中期针对 HTTP/2 报告的一系列 CVE。虽然 Tomcat 没有直接受到影响(恶意输入没有触发过度负载),但我们确实采取了阻止输入的措施与恶意配置文件匹配。

从您的GitHub 评论中,您会看到 POST 的问题。这强烈表明客户端正在多个小数据包中发送 POST 数据,而不是少量的大数据包。一些客户端(例如Chrome)由于缓冲数据的方式而偶尔会这样做。

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

一般来说,数据包减少开销计数,非数据包增加开销计数,并且(潜在的)恶意数据包显着增加开销计数。这个想法是,一个已建立的、通常表现良好的连接应该能够在偶尔的“可疑”数据包中幸存下来,但超过这个数就会很快触发连接关闭。

对于小 POST 数据包,关键配置设置是:

  • overheadCountFactor
  • overheadDataThreshold

开销计数从 -10 开始。对于每个收到的 DATA 帧,它都会减少 1。对于每个 SETTINGS、PRIORITY 和 PING 帧,它都会增加 。如果overheadCountFactor开销计数超过 0,则连接将关闭。

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

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

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

为了解决这个问题,我的建议是首先看看客户。为什么它会发送小的非最终数据帧以及可以采取什么措施来阻止它?

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