Nginx负载均衡默认采用轮询算法,通过upstream块配置后端服务器,支持加权轮询、ip_hash、least_conn等策略,并可结合max_fails、fail_timeout等参数实现健康检查与自动剔除故障节点。

直接在 Nginx 负载均衡层通过 log_format 记录并识别异常大请求包,是低成本、高实效的一线防御手段。关键不在于“记录全部”,而在于精准捕获请求体大小、头部长度、总字节数等可量化指标,并结合业务基线快速标出偏离值。
重点记录哪些长度变量
在 http 块中定义日志格式时,必须包含以下三类长度字段:
- $request_length:完整请求行 + 请求头 + 请求体的总字节数(单位:bytes),最能反映“巨型请求”攻击特征,如 UDP Flood 反射放大或恶意上传场景
- $body_bytes_sent:响应体实际发送字节数,可用于反向验证——若请求极大但响应极小(如 0 或几十字节),高度可疑
-
$request_body_length(需启用
lua-resty-core或开启proxy_buffering off配合读取):精确获取 POST/PUT 请求体大小;普通 Nginx 默认不记录该变量,但可通过set_by_lua_block或map+proxy_set_header间接注入
实战可用的 log_format 示例
推荐如下精简但信息完备的格式(适配 ELK 或 Prometheus + Loki 日志分析):
log_format attack_probe '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time $upstream_http_content_length';说明:
- 保留
$request_length和$body_bytes_sent形成比值关系(例如request_length / body_bytes_sent > 1000),可快速筛选“发得多、回得少”的畸形交互 - 添加
$upstream_http_content_length可对比后端返回内容长度,辅助判断是否被后端截断或伪造 - 避免记录
$request_body(性能开销大且有隐私风险),用长度代替内容更安全高效
如何从日志中识别攻击包
不是看单次超大值,而是关注统计分布与业务背离:
- 正常用户请求
$request_length多数集中在 500–3000 字节(含 Cookie、常规表单);若某时段出现大量 >10KB 的请求,尤其集中在同一路径(如/api/upload或/graphql),即为高危信号 - 检查
$request_length > 100000且$body_bytes_sent 的请求组合,常见于 Slowloris 变种或畸形 HTTP/2 帧攻击 - 配合
$http_content_type字段过滤:若application/octet-stream或multipart/form-data类型请求中$request_length突增,大概率是文件上传类 CC 或资源耗尽攻击
联动响应建议
日志只是“眼睛”,需与限流策略闭环:
- 用
limit_req按$request_length分级限速:例如对request_length > 50KB的请求强制走严格令牌桶(burst=1, nodelay) - 在 WAF 或 OpenResty 中基于日志发现的阈值,动态生成临时黑名单:如 5 分钟内出现 3 次
request_length > 200KB的 IP,自动加入 10 分钟封禁列表 - 将
$request_length作为 Prometheus 指标暴露(通过nginx-lua-prometheus),设置告警规则:avg_over_time(nginx_http_request_length_sum[5m]) / avg_over_time(nginx_http_request_length_count[5m]) > 15000

















