nginx 1.31.0 与 1.30.x:反代配置要跟着改的几处
nginx 1.31.0 于 2026-05-13 发布,1.30.x 是 2026-04-14 拉出的稳定分支。两个线里对反向代理影响最直接的是 1.31.0 对 HTTP/2、HTTP/3 请求头的拒绝策略,以及 1.29.7 起 upstream keepalive 的默认值变化——后者会让不少老配置里手写的 proxy_set_header Connection "" 变成冗余。
变更记录:、
1.31.0:h2/h3 请求里的 hop-by-hop 头直接拒绝
1.31.0 的 Change 项写明:nginx 拒绝 HTTP/2 和 HTTP/3 请求中携带 Connection、Proxy-Connection、Keep-Alive、Transfer-Encoding、Upgrade 头,以及 TE 头除 trailers 以外的任何值。
原因和这些头在 h2/h3 里的合法性有关:它们是 HTTP/1.1 的逐跳(hop-by-hop)头,HTTP/2 与 HTTP/3 的连接语义由协议层自己承担,请求里再出现这些字段属于违规。RFC 7540/9113 明确要求把 Connection 相关字段视为 malformed。
实际影响有两类。
一类是客户端侧。老客户端、SDK 或中间件把 HTTP/1.1 的请求头原样搬进 h2 会话,就会拿到 400。常见的是某个代理层做了 header 透传但没按协议版本过滤。
另一类是 nginx 自己做 h2 反代时。1.29.4 起 proxy 模块已支持 HTTP/2,上游返回的这些头会进入 nginx 的响应处理路径,同样要按新规则对待。
排查顺序:
# 1. 看 error/access log 里的 400,以及 h2 相关的协议错误
grep -E ' 400 |HTTP/2|client sent invalid' /var/log/nginx/error.log
# 2. 用 curl 直接复现,先确认是 h2 特有
curl -v --http2 https://example.com/path
curl -v --http1.1 https://example.com/path
# 3. 检查配置里有没有显式传递这些头
grep -nE 'proxy_set_header\s+(Connection|Proxy-Connection|Keep-Alive|Transfer-Encoding|Upgrade|TE)' /etc/nginx/nginx.conf /etc/nginx/conf.d/*.conf
如果 --http2 复现 400 而 --http1.1 正常,基本就是客户端或中间件多带了 hop-by-hop 头,而不是 nginx 配置本身写错。
keepalive 默认化之后,老配置要清理
1.29.7 的 Change 项有四处联动:
- upstream 里的
keepalive指令默认开启; ngx_http_proxy_module默认支持 keepalive;proxy_http_version默认值改为 1.1;- 默认不再发送
Connection代理头。
这就是很多老配置里出现 proxy_set_header Connection ""; 的由来——在旧版本里,要靠它清掉默认的 Connection: close 才能复用连接。升级到 1.29.7 及以上之后,这一行不再必要;如果配置里同时还显式写了 proxy_http_version 1.1,也属于重复。
同版本新增:
keepalive指令的local参数;listen的multipath参数。
新增指令与模块
- 1.31.0 新增
least_time指令,作用于upstream块,按响应时间选后端。 - 1.31.0 新增 stream 模块的
proxy_ssl_alpn指令。 - 1.31.0 新增
ngx_http_tunnel_module,并在auth_basic、satisfy、auth_delay中支持对代理的认证。 - 1.29.8 新增
max_headers指令,用于限制请求头数量,同时带来 OpenSSL 4.0 兼容、geo块内include支持通配符。 - 1.29.6 引入会话保持:http 模块 upstream 中的
sticky指令,server指令支持route和drain参数,并限制 QUIC stateless reset 包的大小与速率。 - 1.31.0 变更:
sticky模块可用--without-http_upstream_sticky_module关闭,旧的--without-http_upstream_sticky已废弃。 - 1.31.0 变更:
ngx_http_dav_module在 COPY/MOVE 的源与目标相同、或存在父子集合关系时直接拒绝。 - 1.31.0 变更:
invalid alert、record layer failure、SSL alert number N这类 SSL 错误的日志级别从 crit 降到 info。 - 1.29.4 起 proxy 模块支持 HTTP/2;新增
ssl_ech_file;host/port 按 RFC 3986 更严格校验;chunked body 里单个 LF 作为行结束符视为错误。 - 1.29.3 新增
add_header_inherit、add_trailer_inherit、$request_port、$is_request_port、$ssl_sigalg、$ssl_client_sigalg,以及geo的volatile参数。
安全修复
1.31.0 修了六处:
proxy_set_body可向 HTTP/2 后端注入数据(CVE-2026-42926);ngx_http_rewrite_module处理构造请求时堆溢出,可能导致 RCE(CVE-2026-42945);ngx_http_scgi_module、ngx_http_uwsgi_module处理构造响应时堆越界读,泄露 worker 内存或段错误(CVE-2026-42946);charset_map从 UTF-8 解码时堆越界读(CVE-2026-42934);- HTTP/3 连接迁移可让新 QUIC 流在校验前收到新客户端地址,形成地址欺骗(CVE-2026-40460);
- 使用
ssl_ocsp时处理 DNS 服务器响应存在 use-after-free(CVE-2026-40701)。
另外修了两个功能 bug:使用 proxy_set_body 或 proxy_pass_request_body 时 HTTP/2 后端连接可能不被缓存;HTTP/0.9、SCGI、uWSGI 响应在首行未完整读取时可能传输错误。
1.29.7 修了:
- 在带
alias的 location 中处理 COPY/MOVE 的缓冲区溢出,可改写文档根之外的源/目标路径(CVE-2026-27654); - 32 位平台上构造 mp4 导致崩溃(CVE-2026-27784),以及 mp4 崩溃等其他影响(CVE-2026-32647);
- 启用 auth retry 且使用 CRAM-MD5 或 APOP 认证时段错误(CVE-2026-27651);
- PTR DNS 记录可向
auth_http请求注入数据、向后端 SMTP 注入 XCLIENT(CVE-2026-28753); - stream 模块中即使 OCSP 拒绝客户端证书,SSL 握手仍可能成功(CVE-2026-28755)。
1.29.5 修了 SSL 后端响应可被注入明文数据(CVE-2026-1642),以及切换到下一个 gRPC 或 HTTP/2 后端后的 use-after-free。
升级检查清单
- h2/h3 客户端:抓取 400 响应,确认是不是 hop-by-hop 头透传导致;检查配置里有没有显式
proxy_set_header传Connection、TE、Upgrade之类。 - keepalive 去重:删掉
proxy_set_header Connection ""与显式proxy_http_version 1.1,除非有明确理由保留;确认 upstream 的 keepalive 行为符合预期。 max_headers与请求头上限:升级后按业务实际调整,避免默认值扛不住大 header 场景。sticky/drain:若用了会话保持,注意--without-http_upstream_sticky已废弃,改用--without-http_upstream_sticky_module。- mp4 与 dav 模块暴露面:不用就编译期关掉;用了就核对 1.31.0 对 COPY/MOVE 同源与父子关系的拒绝行为是否影响现有上传/迁移流程。
- QUIC / HTTP/3:涉及连接迁移的场景,确认已带上 1.31.0 的地址校验修复。