Nginx需通过自定义log_format嵌入$limit_req_status、$limit_conn_status等变量,按拦截类型分路径或打标记录,并关联限流参数与响应头,再经Filebeat+Logstash实现聚合分析与容量预警。

要让 Nginx 日志真实反映防刷与限流拦截全过程,不能只依赖默认 access_log,必须主动扩展日志变量、区分拦截类型、标记触发条件,并确保日志字段能被后续分析工具识别。
用自定义日志格式记录限流与拦截动作
默认日志不包含限流状态,需在 http 块中定义含关键变量的日志格式:
-
$limit_req_status:返回 503 或 429 时为“503”或“429”,正常请求为空 -
$limit_conn_status:连接数超限时为“503”,否则为空 -
$request_time和$upstream_response_time:对比可判断是否卡在限流排队阶段 -
$http_user_agent和$http_x_forwarded_for:辅助识别扫描器或伪造 IP
示例配置:
log_format security '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" $request_time $upstream_response_time ' '$limit_req_status $limit_conn_status $http_x_forwarded_for';再在 server 或 location 中启用:access_log /var/log/nginx/security.log security;
区分不同拦截场景并打标记录
单一日志难以归因,建议按策略分路径或加条件变量,让每条日志自带“原因标签”:
- 登录接口限流日志单独输出:
access_log /var/log/nginx/login_blocked.log security if=$limit_req_status;(仅记录触发限流的请求) - 对已知扫描 UA 的拦截,用
map打标:
map $http_user_agent $ua_blocked {~*(nmap|sqlmap|nikto) "1"; default "";}
log_format security "... $ua_blocked"; - 敏感路径(如
/api/sms/send)被限流时,可在 location 内加固定字段:
set $log_tag "sms_rate_limited";
log_format security "... $log_tag";
配合限流指令输出可追溯的上下文
仅记录状态码不够,需把限流参数也显式落盘,方便回溯策略是否生效:
- 在
limit_req后加limit_req_status 429,确保返回码统一且可过滤 - 用
add_header X-RateLimit-Limit "5"和X-RateLimit-Remaining(需 Lua 或 OpenResty 扩展)向响应头注入配额信息,日志可通过$sent_http_x_ratelimit_limit捕获 - 对 burst 队列溢出场景,
nodelay下请求直接失败,burst值应出现在日志注释或监控指标中,避免误判为后端故障
日志联动分析与告警建议
原始日志只是起点,真正起效靠后续处理:
- 用 Filebeat + Logstash 提取
$limit_req_status非空值,聚合统计每 IP 触发频次,自动加入临时黑名单 - 对连续 5 分钟内
$ua_blocked=1的 IP,触发告警并同步写入deny指令或 geo 封禁列表 - 将
$request_time > 0.5且$limit_req_status=503的请求单独告警——说明限流桶已满,用户正在排队等待,是容量预警信号


















