Nginx如何应付HTTP/2 快速重置攻击?


最近发现的与 HTTP/2 协议相关的漏洞:CVE-2023-44487:在某些情况下,可以利用此漏洞对 NGINX Open Source、NGINX Plus 以及实现 HTTP/2 规范服务器端部分的相关产品执行拒绝服务攻击。为了保护您的系统免受此攻击,我们建议立即更新您的 NGINX 配置。

HTTP/2 流重置的问题
与服务器建立连接后,HTTP/2 协议允许客户端发起并发流进行数据交换。与协议的先前迭代不同,如果最终用户决定离开页面或出于任何其他原因停止数据交换,HTTP/2 提供了一种取消流的方法。它通过向服务器发出 RST_STREAM 帧来实现此目的,从而使其免于执行不必要的工作。

该漏洞是通过在已建立的连接上启动并快速取消大量 HTTP/2 流来利用的,从而绕过服务器的并发流最大值。发生这种情况是因为传入流的重置速度比后续流到达的速度快,从而允许客户端在不达到其配置阈值的情况下使服务器过载。

对 NGINX 的影响
出于性能和资源消耗的原因,NGINX 将并发流的数量限制为默认值 128(请参阅http2_max_concurrent_streams)。此外,为了最佳地平衡网络和服务器性能,NGINX 允许客户端默认使用 HTTP keepalive 保持最多 1000 个请求的 HTTP 连接(请参阅keepalive_requests)。

通过依赖默认的 keepalive 限制,NGINX 可以防止此类攻击。

如果 NGINX 配置的 keepalive 远高于默认和推荐的设置,则攻击可能会耗尽系统资源。当发生流重置时,HTTP/2 协议要求该流上没有后续数据返回到客户端。通常,重置会导致以优雅地处理取消的任务形式出现的服务器开销可以忽略不计。然而,绕过 NGINX 的流阈值使客户端能够利用这种开销,并通过快速启动数千个流来放大它。这会迫使服务器 CPU 达到峰值,从而拒绝向合法客户端提供服务。

减轻攻击风险的步骤
作为功​​能齐全的服务器和代理,NGINX 为管理员提供了减轻拒绝服务攻击的强大工具。要利用这些功能,必须对 NGINX 配置文件进行以下更新,从而最大限度地减少服务器的攻击面:

  • keepalive_requests应保持默认设置 1000 个请求
  • http2_max_concurrent_streams应保持默认设置 128 个流

我们还建议添加这些安全措施作为最佳实践:
  • limit_conn对单个客户端允许的连接数强制实施限制。该指令应添加平衡应用程序性能和安全性的合理设置。
  • limit_req对单个客户端在给定时间内处理的请求数量强制执行限制。该指令应添加平衡应用程序性能和安全性的合理设置。

map $http2 $v1ip {
    default "";
   
""  $binary_remote_addr;
}
map $http2 $v2ip {
    default $binary_remote_addr;
   
"" "";
}

limit_conn_zone $v1ip zone=v1ips:10m;
limit_conn v1ips 10;

limit_conn_zone $v2ip zone=v2ips:10m;
limit_conn v2ips 125;

补丁
我们发布了一个补丁来提高这些条件下的系统稳定性。为了防范此类威胁,我们建议 NGINX 开源用户从最新的代码库重建二进制文件,并且 NGINX Plus 客户立即更新到最新的软件包(R29p1 或 R30p1)。

为了确保尽早检测到 NGINX 上的洪水攻击,该补丁对一个事件循环中可以引入的新流的数量进行了限制。此限制设置为使用http2_max_concurrent_streams指令配置的值的两倍。即使从未达到最大阈值,也会应用该限制,例如发送请求后立即重置流(如本次攻击的情况)。