$request_length 是 nginx 中记录客户端请求总字节数的字段,异常大值常表征 fuzzing、cc 或扫描行为;需基于域名、uri 等维度建模动态基线(如 p95+20%),结合 ip/asn/uri/headers/节奏等多维指纹识别恶意请求,并通过 map+redis+外部分析实现精准封禁。

$request_length 是 Nginx 日志中的一个关键字段,表示客户端发送的完整 HTTP 请求(含请求行、请求头、请求体)的总字节数。它不包含响应数据,仅反映入站请求的原始体积。该指标本身无害,但当其在单位时间内出现显著偏离正常分布的高频大值时,往往指向恶意探测行为——例如利用超长 User-Agent、畸形 Cookie、重复参数或构造巨量 POST body 进行的 fuzzing、CC 探测、漏洞扫描或 DoS 尝试。
识别异常 $request_length 的核心逻辑
静态阈值(如 >10KB 封禁)易误伤合法业务(如大文件上传、富文本提交)。应基于动态基线建模:
- 按域名、URI 路径、User-Agent 类型等维度分组,分别统计每分钟/每5分钟的 $request_length 分位数(P95/P99)和标准差
- 对每个分组维护滑动时间窗口(如最近60分钟)的基准:均值 ± 2σ 或 P95 上浮20% 作为动态上限
- 单个请求若超过当前分组动态上限,且连续3次触发,则标记为“高置信度异常”
构建轻量级动态画像的必要维度
仅看长度会漏判协同攻击。需关联以下字段生成设备/行为指纹:
- IP + ASN + 地理位置:同一 ASN 下多 IP 集中发送超长请求,大概率是扫描器集群
- URI pattern + HTTP method:GET 请求携带 8KB query string,或对 /wp-admin/ 发送 15KB POST,风险极高
- Header 异常组合:如空 Host、重复 Content-Length、不匹配的 Transfer-Encoding、非常规 User-Agent(含 sqlmap/nikto 关键词)
- 请求节奏特征:10秒内发起7个 >5KB 请求,间隔均匀(±200ms),非人类操作特征明显
在 Nginx 层实现自动封禁的可行路径
纯 Nginx 可通过 limit_req + map + 自定义日志变量联动实现基础拦截,但复杂画像建议后端协同:
- 用
map指令将 $request_length 映射为风险等级(如:$req_len_level),再结合 $http_user_agent 等做嵌套判断 - 将高风险请求写入共享内存 zone 或 Redis,由外部 agent(如 Python 脚本)实时聚合分析,生成封禁规则推送到 Nginx 的
geo或map变量 - 对确认恶意 IP,可调用 fail2ban 监控 Nginx 错误日志,或直接注入 iptables 规则(需注意连接跟踪开销)
规避误封与运营注意事项
大报文未必恶意,需留出安全出口:
- 对已知上传接口(如 /api/v1/upload)白名单放行,或单独设置更高阈值
- 封禁前先返回 403 + 自定义 Header(如 X-Blocked-Reason: large-request),便于前端日志回溯
- 所有封禁动作必须记录完整上下文(时间、IP、$request_length、$request_uri、$http_referer),供人工复核
- 动态基线需每日凌晨自动重置,并保留7天历史曲线,支持人工干预修正











