client_header_timeout是防御Slowloris类慢速头攻击最直接有效的手段,它仅监控HTTP请求头是否在规定时间内完成发送(从首字节到\r\n\r\n),超时即返回408并关闭连接,不进入upstream。

client_header_timeout 是识别和切断慢速头攻击(如 Slowloris)最直接有效的手段。它不处理请求内容,只盯住“HTTP 请求头有没有按时发完”这一环节——从 TCP 连接建立后收到第一个字节开始计时,到完整收到 \r\n\r\n(空行)为止。一旦超时,Nginx 立即关闭连接、返回 408,不进 upstream,不占后端资源。
它专防什么,不防什么
Slowloris 类攻击的核心动作是:建一堆连接,但每次只发一点点请求头(比如只发 GET / HTTP/1.1 就停住,或每 10–15 秒补一个随机 header),让 Nginx 长期卡在“等头收全”的状态。client_header_timeout 正好卡在这个点上。
- ✅ 防:连接已建、头只发一半、迟迟不发空行的拖延行为
- ❌ 不防:头发完了但 body 慢传(那是 client_body_timeout 的事)
- ❌ 不防:响应发得慢(那是 send_timeout 或后端性能问题)
- ❌ 不防:合法大 Cookie 或多自定义头导致头本身较大(需配合 client_header_buffer_size 和 large_client_header_buffers)
生产环境推荐值与取舍逻辑
默认 60 秒太宽松,等于给攻击者留足时间填满所有 worker_connections。合理值需兼顾真实延迟与防御强度:
- 标准 Web/API 服务:设为 7 秒。浏览器、curl、主流 SDK 均在毫秒级完成头发送,7 秒足以覆盖高延迟移动网络或中间代理抖动
- 内网或可信网关后:可压至 3–5 秒,链路稳定,无 NAT 或深度检测设备干扰
- 含大量 Cookie 或 SSO 头的场景:先开启日志记录 $request_time 和 $status,观察正常请求头接收耗时的 P99 值,再加 2–3 秒缓冲,通常不超过 15 秒
必须同步配置的关键项
单设 client_header_timeout 效果有限,需与其他参数咬合形成闭环:
- reset_timedout_connection on;:超时后发 RST 包而非 FIN,快速释放 socket 和文件句柄,避免 TIME_WAIT 滞留
- limit_conn addr 10;(配合 limit_conn_zone $binary_remote_addr zone=addr:10m;):限制单 IP 初始并发连接数,防攻击者用多个源 IP 扫荡
- client_body_timeout 10s;:防止攻击者绕过头阶段,发完头后立刻转入慢传 body
- keepalive_timeout 15s;:缩短空闲长连接存活时间,避免被复用为扫描通道
验证是否真正生效
不要只看配置 reload 成功,要实测行为:
- 用 telnet 连接后只输入 GET / 回车,不发 Host、不发空行,等待约设定值 +2 秒 —— 应看到连接被服务器主动断开(非客户端超时)
- 检查 error.log 是否出现 client timed out (110: Connection timed out) while reading client request headers
- 观察活跃连接中 reading 状态数是否明显下降,尤其在流量低谷时段突增的长期 reading 连接应显著减少

















