Nginx 400 错误应通过主动拦截而非事后修复,核心是合理配置 client_header_buffer_size 与 large_client_header_buffers 协同限长,并配合 HTTP/2 参数、超时控制及源头收敛策略。

Nginx 负载均衡中遇到 400 错误,若由客户端恶意构造超长请求头引发,核心不是“修复”而是“主动拦截+合理设限”。它不靠事后过滤,而是在请求解析第一阶段就做内存分配决策:够用则接纳,超标即拒绝并返回 400,不进入后续代理或后端流程。关键在平衡安全性与业务兼容性。
必须协同配置两级缓冲参数
单改 client_header_buffer_size 无效,它只是“第一道门”,真正起作用的是和 large_client_header_buffers 的配合关系:
-
client_header_buffer_size 4k;
设为略大于业务中常见最长单行头(如 JWT、Cookie),推荐 4k 或 8k;不能超过后者单块大小 -
large_client_header_buffers 4 16k;
表示最多启用 4 块缓冲,每块 16KB;单块大小必须 ≥ 前者,否则 Nginx 启动失败
这两个指令必须放在 http 或 server 块顶层,不可写在 location 内——因为请求头解析发生在路由匹配之前。
HTTP/2 场景需额外加固
若监听 listen 443 ssl http2;,还需补充:
-
http2_max_header_size 32k;
控制整个头部块总大小(所有字段加起来),建议设为与large_client_header_buffers总上限一致(如 4×16k=64k,此处可设 32k 或 64k) -
http2_max_field_size 8k;
限制单个 header 字段值长度,防超长User-Agent或伪造Authorization
配合超时与行为控制防慢速攻击
恶意构造不一定靠“长”,也可能靠“慢”——逐字节发送头字段,长期占用 worker 连接:
-
client_header_timeout 8s;
读取请求头超过 8 秒直接断连 -
reset_timedout_connection on;
对超时连接发 RST,快速释放内存 -
underscores_in_headers off;
禁用下划线,避免绕过鉴权或框架解析歧义(如X_Api_Key被误解析为x-api-key)
源头收敛比调参更可靠
缓冲区调大只是兜底,长期应减少攻击面:
- 前端避免将用户画像、Token 原文等塞进 Cookie,改用服务端 session + 短 ID
- 第三方埋点脚本产生的冗余 Cookie(如
_ga、amplitude_id)做域名隔离或子域清理 - 后端响应
Set-Cookie时校验总长,超长值主动截断或拒绝下发
验证是否生效:
修改后 nginx -s reload,用 curl -H "X-Fake: $(printf 'a%.0s' {1..33000})" 测试边界,观察是否稳定返回 400 且 error.log 出现 request header or cookie too large 日志——说明策略已生效。


















