client_body_timeout核心作用是限制客户端发送请求体的空闲间隔时间,超时即断连并返回408;它不控制总上传时长,仅防慢速攻击,推荐设为10s并配合client_max_body_size等使用。

client_body_timeout 的核心作用,是控制客户端发送请求体(比如 POST 数据)的等待时间。它不决定能传多大文件,而是决定“发得有多慢就会被断掉”。调优的关键不是设得越长越好,而是让异常慢速行为在占用资源前就被清理。
client_body_timeout 是怎么工作的
当 Nginx 收到一个完整请求头(含 Content-Length 或 Transfer-Encoding: chunked),就认为要接收请求体。此时启动计时器:
- 如果客户端在设定时间内未开始发送请求体,直接返回 408 Request Timeout
- 如果已开始发送,但两次数据包之间间隔超过该值,同样触发超时并关闭连接
- 注意:这个超时是“空闲间隔”超时,不是整个上传耗时限制(总上传时间由 client_max_body_size + buffer + 后端处理共同决定)
为什么默认值(60s)在生产中容易出问题
Slow body 攻击正是利用较长的等待窗口:攻击者声明 Content-Length: 10000000,然后每 30 秒发 1 字节。Nginx 会为每个这样的连接持续分配内存缓冲区(client_body_buffer_size)、保持 socket、占用 worker 连接槽位——而一个普通 worker 可能只支持 8K–16K 并发连接,几百个慢连接就能打满。
- Windows 系统下尤其敏感:句柄数硬上限约 16K,超时过长会快速堆积 TIME_WAIT 和半开连接
- 即使有 limit_conn,也只限制“已建立连接数”,对正在缓慢发体的连接无效
- 内存池不会释放:只要请求没结束,请求级内存池就一直挂着,缓冲区占用不回收
实战推荐配置与搭配要点
目标是让慢速 POST 在 5–15 秒内暴露并中断,同时不影响真实用户(如弱网上传、大表单提交)。关键不在单点数值,而在组合生效:
- client_body_timeout 10s:主流推荐值。覆盖绝大多数正常行为(浏览器/APP 一般 1–3 秒内开始传体),又能快速截断慢速攻击
- client_header_timeout 10s:配套设置,防 Slow headers,避免连接卡在头部阶段
- reset_timedout_connection on:强制发送 RST 包而非 FIN,立即释放 socket 和句柄,不等四次挥手
- client_max_body_size 20M:配合使用。防止攻击者用极大 Content-Length 占满缓冲区;超出直接 413,不进 timeout 流程
- client_body_buffer_size 1M:设为略大于常见 POST 体(如 JSON 表单、小图 Base64),避免频繁落盘;过大易被慢速体长期持占内存
验证是否生效的小技巧
不用等真实攻击,可用 curl 模拟慢速 POST 验证逻辑:
(终端执行,模拟每 15 秒发 1 字节)yes "A" | head -c 1000000 | awk '{printf "%s"; system("sleep 15")}' | curl -X POST --data-binary @- http://your-domain.com/api
- 若配置正确,约 10 秒后连接被断,Nginx error log 出现
client timed out (110: Connection timed out) while reading client request body - 观察
netstat -an | grep :443 | grep ESTAB | wc -l是否不再异常增长 - 检查 access log 中 408 状态码比例——上线初期略升属正常,稳定后应趋近于 0.1% 以内


















