$request_length是最有效的攻击识别切入点——它精确反映请求原始字节数,配合自定义日志格式可快速定位超长报文、区分正常业务与恶意填充;需显式加入log_format,并结合阈值筛选、client_max_body_size验证及高危路径定向告警形成闭环防御。

直接看 $request_length 是最有效的切入点——它代表整个请求的原始字节数(含方法、URI、Header、Body),对 POST 攻击尤其敏感。配合合理 log_format,能快速识别超长报文、定位源头、区分真实业务与恶意构造。
明确记录 request_length 并增强上下文
默认 combined 格式不包含 $request_length,必须自定义日志格式:
log_format attack_probe '$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.log attack_probe;关键点:
-
$request_length必须显式加入,它是判断“是否异常大”的第一标尺 - 补充
$request_time和$upstream_response_time,可辅助判断是客户端发包慢、还是后端卡住导致缓冲堆积 - 保留
$http_x_forwarded_for,避免因代理层丢失真实源 IP
示例:一条日志中出现
POST /api/submit HTTP/1.12004112849260.0030.002—— 请求长度达 1.2MB,但只返回 41 字节,极可能是恶意填充 Body 的攻击。
设置阈值并用日志工具快速筛选
生产环境不靠肉眼扫日志。将 $request_length 当作数值字段导入 ELK、Loki 或甚至 awk 做实时过滤:
# 查找单次请求 > 2MB 的记录(单位:字节)
awk '$12 > 2097152 {print}' /var/log/nginx/access.log
# 按 IP 统计超长请求频次(假设 $request_length 是第12列)
awk '$12 > 1048576 {ip[$1]++} END {for (i in ip) print i, ip[i]}' /var/log/nginx/access.log | sort -k2 -nr | head -20常见攻击特征:
- 同一 IP 在短时间(如 1 分钟)内高频发送
request_length > 1MB的 POST -
request_method为 POST,但request_uri指向非上传接口(如/login、/search) -
body_bytes_sent极小(
关联 client_max_body_size 配置做闭环验证
$request_length 异常高,往往意味着已触达 Nginx 的请求体限制边界。检查是否真因配置不足被截断:
- 若日志中对应请求
status为413 Request Entity Too Large,确认client_max_body_size是否过小(如仍设默认1m,而业务实际需10m) - 若
status是400 Bad Request且错误日志含"client intended to send too large body",说明请求头+体总长超出缓冲上限,需同步调大client_header_buffer_size和large_client_header_buffers - 若大量超长请求
status为200或500,则更可能是应用层未校验、被成功注入,此时$request_length是发现入口,还需结合$request_body(需 Lua 模块)进一步分析内容
补充:对高危 POST 接口做定向日志强化
对登录、表单提交、API 入口等重点路径,可在 location 块单独启用更细粒度记录:
location ~ ^/(login|api/v\d+/submit|wp-admin/admin-ajax\.php) {
# 只对这些路径记录完整请求体(需启用 lua + client_body_buffer_size 足够)
log_by_lua_block {
if ngx.var.request_method == "POST" and tonumber(ngx.var.request_length) > 524288 then
ngx.log(ngx.WARN, "Huge POST from ", ngx.var.remote_addr,
" length=", ngx.var.request_length,
" uri=", ngx.var.request_uri)
end
}
}这种方式不写入 access_log,但通过 warn 级别错误日志快速告警,避免日志爆炸,也绕过 access_log 缓存延迟。
不复杂但容易忽略。

















