HTTP/2 请求头内存耗尽¶
Traefik 通过 Go 标准库提供 HTTP/2 服务。 在 HTTP/2 中,一个连接可以复用多个并发请求,每个请求都有自己的请求头块。
客户端可以结合 HPACK 请求头压缩和 HTTP/2 流量控制窗口,将少量网络传输数据扩展为代理上的大量内存分配,并通过停滞数据流使这些内存一直无法释放。 当并发流和连接足够多时,就可能耗尽可用内存并导致 Traefik 进程终止。
以下两个入口点选项可以限制这一风险,建议同时使用。
限制请求头大小¶
maxHeaderBytes 选项限制 Traefik 为每个请求读取的请求头大小,单位为字节。
将其从默认值(1048576,即 1 MiB)调低到能够容纳最大合法请求头的最小值,可以让 Traefik 在请求头块被放大之前就拒绝超大请求头。
entryPoints:
websecure:
address: ':443'
http:
maxHeaderBytes: 65536[entryPoints.websecure]
address = ":443"
[entryPoints.websecure.http]
maxHeaderBytes = 65536--entryPoints.websecure.address=:443
--entryPoints.websecure.http.maxHeaderBytes=65536限制每个连接的并发流数量¶
maxConcurrentStreams 选项限制每个客户端能够在单个连接上发起的并发 HTTP/2 流数量(默认值为 250)。
调低该值可减少单个连接能够持续占用的内存量。
entryPoints:
websecure:
address: ':443'
http2:
maxConcurrentStreams: 100[entryPoints.websecure]
address = ":443"
[entryPoints.websecure.http2]
maxConcurrentStreams = 100--entryPoints.websecure.address=:443
--entryPoints.websecure.http2.maxConcurrentStreams=100纵深防御
这两个限制可以约束单个连接的内存消耗。 如需进一步防护,还应在前置负载均衡器或防火墙上限制每个来源 IP 的并发连接数及请求速率,并为 Traefik 实例配置足够的内存,以处理预期的合法负载。