$request_length是识别扫描器、CC攻击或畸形请求的关键指标,因其能反映请求总字节数,异常大值(如MB级)常源于恶意构造的超长URL、巨量POST body等。

直接用 $request_length 配合自定义日志格式,能快速识别体积异常大的请求(比如超长 URL、恶意构造的巨量 POST body),这是识别扫描器、CC 攻击或畸形请求的第一道线索。
为什么 $request_length 是关键指标
$request_length 表示整个 HTTP 请求的字节数,含请求行、全部请求头和请求体。正常用户请求通常在几百到几 KB;而攻击类请求可能达 MB 级,例如:
- 自动化工具批量提交超长参数(如 base64 编码的 payload 拼接在 query string)
- 伪造的 multipart/form-data 含重复字段或巨型二进制块
- 利用漏洞反复追加 Cookie 或 Header 字段耗尽服务端缓冲区
在 log_format 中显式记录并监控
确保你的 log_format 明确包含 $request_length,便于后续分析:
log_format attack_detect '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'$request_time $request_length '
'"$http_user_agent" "$http_referer"';然后启用该格式:
access_log /var/log/nginx/attack.log attack_detect;
这样每条日志末尾都会带请求总长度,方便用 awk、grep 或 ELK 快速筛选:
# 查看大于 1MB 的请求
awk '$12 > 1048576 {print}' /var/log/nginx/attack.log用 limit_req_zone 做初步拦截(防放大)
仅靠日志发现太被动,建议结合限流模块主动压制大请求频次。例如:对单个 IP,限制「每秒最多 3 个 request_length 超过 50KB 的请求」:
http {
# 定义一个按 IP + 大请求标记的限流区域
map $request_length $large_req_key {
~^[5-9][0-9]{4,} $binary_remote_addr;
default "";
}
limit_req_zone $large_req_key zone=large_req:10m rate=3r/s;
<pre class="brush:php;toolbar:false;">server {
location / {
limit_req zone=large_req burst=5 nodelay;
proxy_pass http://backend;
}
}}
说明:
-
map将$request_length转为非空字符串(只匹配 ≥50000 字节的请求) - 只有真正触发大请求的 IP 才进入限流区域,不影响普通流量
-
nodelay确保超限立即拒绝(返回 503),避免排队堆积
配合 if + return 实现精准阻断
对明确超过阈值(如 200KB)的请求,可直接拒绝,不进后端也不记 access log(减少日志污染):
server {
# 先判断,再决定是否放行
if ($request_length > 2097152) {
return 400 "Request too large";
}
<pre class="brush:php;toolbar:false;">location / {
proxy_pass http://backend;
}}
注意:if 在 location 外使用是安全的,且 Nginx 会先执行它;该方式适合硬性封禁已知风险尺寸,响应快、无额外开销。

















