$request_length是定位异常大报文引发连接阻塞最准最快的方式——它在Nginx完整接收请求后立即生效,真实反映网络层实际载荷大小,不受压缩、伪造header影响,能精准暴露Slow Body、Gzip炸弹等“沉默杀手”。

直接看 $request_length 是定位异常大报文引发连接阻塞最准、最快的方式——它在 Nginx 完整接收请求(含请求行、全部 header 和 body)后立即生效,不依赖后端、不解压、不解析,数值真实反映网络层实际载荷大小。一旦该值远超业务合理范围,就极可能造成缓冲区堆积、连接卡住甚至网关级阻塞。
为什么 request_length 能暴露连接阻塞源头
$request_length 统计的是客户端发来的原始字节数,包括方法、URI、所有请求头和整个请求体。它不是 Content-Length 的镜像,也不受 gzip 压缩影响,更不会被恶意伪造的 header 欺骗。当攻击者发送超长 POST(如 50MB 随机字符串)、Slow Body 或 Gzip 炸弹时,Nginx 必须收完整个包才转发或响应,这个过程会持续占用 worker 连接和内存缓冲区。若大量此类请求并发涌入,worker 连接池迅速耗尽,新请求排队等待,表现为“连接慢”“超时多”“status=499/504 骤增”,而 `$request_length` 日志能第一时间把这类“沉默杀手”揪出来。
配置日志格式并保留关键上下文
默认 `combined` 日志不含 `$request_length`,必须显式定义:
log_format long_req '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '$request_length $request_time $upstream_response_time ' '"$http_user_agent" "$http_referer" $http_x_forwarded_for';
access_log /var/log/nginx/access_long.log long_req;
关键点:
- 务必包含 `$request_time`(客户端到 Nginx 接收完成耗时)和 `$upstream_response_time`(Nginx 到后端往返耗时),可区分是“客户端发得慢”还是“后端回得慢”
- 保留 `$http_x_forwarded_for`,避免代理链导致源 IP 丢失
- 单独建日志文件(如
access_long.log),避免污染主日志,也方便按需滚动或采集
用阈值+时间窗口快速识别阻塞特征
单看一个大值没意义,要结合频次与时间分布。典型阻塞信号包括:
- 同一 IP 在 60 秒内出现 ≥ 5 次 `$request_length > 2MB` 的 POST 请求
- `$request_length > 10MB` 且 `$body_bytes_sent
- `$request_length > 5MB` 但 `$upstream_response_time` 为 `-` 或极小(说明根本没发给后端,卡在 Nginx 接收阶段)
可用 awk 实时筛查:
# 统计每分钟内超长请求最多的前 10 个 IP
awk -F' ' '{gsub(/\[/,"",$4); print substr($4,1,16), $1, $12}' /var/log/nginx/access_long.log | awk '$3 > 2097152 {count[$1" "$2]++} END {for (i in count) print i, count[i]}' | sort -k3 -nr | head -10
联动 client_max_body_size 和超时参数做闭环防御
仅记录不够,要形成“监控→验证→拦截”闭环:
- 检查 `client_max_body_size` 是否明显小于高频出现的 `$request_length` 异常值(例如日志里常见 3MB 请求,但配置是 1MB),说明攻击已触发 413,但 Nginx 仍花时间接收完再拒绝——这本身就是资源浪费
- 调低 `client_header_timeout` 和 `client_body_timeout`(如设为 10s),让慢速发包攻击在传输中途就被断连,不等收完
- 对已确认的恶意 IP 段,配合 `limit_req`(基于 `$request_length` 的 map 变量)做动态限流,而非简单封禁
不复杂但容易忽略:真正导致连接阻塞的,往往不是单个巨包,而是几十个“略大但未超限”的请求持续占着连接不放。`$request_length` 配合时间维度分析,才能看清这种温水煮青蛙式的消耗。

















