client_header_timeout 的 408 是防御生效的标志,非配置错误;需配合日志字段与 error_log 级别识别攻击,同时调大缓冲区、合理设超时值避免误杀。

client_header_timeout 本身的作用就是主动触发 408 状态并断连,不是“防止记录 408”,而是让该记录合理、可控、有防护价值。关键在于:它本就会记录 408,但正确配置后,这些 408 是防御生效的信号,而非配置失误的结果。
下面从三个实用角度说明怎么做:
client_header_timeout 的 408 是防御成果,不是错误
- 它只在客户端迟迟不发完请求头(比如只发
GET /就停住,或每 20 秒补一个X-Test:)时才返回 408 - 返回 408 的瞬间,连接被立即关闭,不进 upstream、不占后端资源、不记 access log 中的
$request(即不会留下完整请求行) - 所以日志里看到 408,且
$request_time接近你设的 timeout 值(如 9.98s),恰恰说明配置起效了
让 408 日志真正有用,需配合两处日志配置
-
在
log_format中显式包含关键字段:log_format main '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '$request_time $upstream_connect_time';这样能区分:是真实用户弱网超时(
$request_time ≈ timeout,但 IP 分散、UA 多样),还是攻击特征(同一 IP 短时大量 408,$request_time高度集中在 timeout 值附近) -
开启 error_log 的
info或warn级别:error_log /var/log/nginx/error.log info;
超时时会输出类似:
*1234 client timed out (110: Connection timed out) while reading client request headers
这条日志比 access log 更早、更准,是排查真实攻击的第一线索
避免误杀导致“不该有的 408”
以下情况会让合法请求也掉进 408,需针对性处理:
-
头部过大但缓冲区不足:客户端发了长 Cookie 或 JWT,但
client_header_buffer_size太小,Nginx 在读完前就因缓冲溢出报错(非超时),也可能间接触发 408
→ 建议同步调大:client_header_buffer_size 4k; large_client_header_buffers 4 16k; -
TLS 握手延迟叠加首字节慢:某些老旧移动设备或跨境链路,TCP 建连后首字节可能延迟 3–5 秒
→ 公网服务不要低于 10 秒;含 SSO/多域 Cookie 的后台可设 15 秒,而非盲目压到 5 秒 -
代理或 SDK 行为异常:某版 App SDK 在发完
Host:后卡顿 12 秒才发User-Agent:,实际是自身 bug
→ 先用 error_log +$remote_addr过滤高频 408 IP,确认是否集中于特定客户端版本,再决定调参或推动修复
不复杂但容易忽略。

















