要让grafana展示nginx安全防护模块拦截日志大盘,核心是将拦截行为转化为结构化日志事件,需在nginx中通过map定义block_reason、log_format注入安全字段、location中return 403触发记录;再经loki/filebeat/sls提取block_reason为标签;最后在grafana中构建趋势图、来源top10、规则命中率及误拦排查面板,并添加变量筛选、403告警与日志联动告警。

要让 Grafana 展示 Nginx 安全防护模块的拦截日志大盘,核心不是“画图”,而是把拦截行为变成可采集、可打标、可聚合的结构化日志事件。Nginx 本身不内置 WAF,但可通过 if + return 403/444、map 变量或 OpenResty 的 lua-resty-waf 等方式实现拦截逻辑,关键在于:**每条拦截日志必须明确记录“谁被拦、为什么拦、拦在哪条规则”**。
一、Nginx 配置:输出带防护语义的日志字段
在 log_format 中显式注入拦截原因变量,避免事后靠正则硬匹配。推荐用 map 预定义拦截标签:
-
定义拦截类型映射:
map $request_uri $block_reason {<br> ~*\.(bak|conf|sql|env)$ "file_ext_block";<br> ~*union.*select|base64_decode "sql_xss_payload";<br> ~*nmap|sqlmap|nikto "scanner_ua";<br> default "none";<br> } -
新增日志格式(含安全字段):
log_format sec_log '$remote_addr - $remote_user [$time_local] "$request" '<br> '$status $body_bytes_sent "$http_referer" "$http_user_agent" '<br> '$request_time "$upstream_response_time" "$upstream_addr" '<br> '$block_reason "$http_x_forwarded_for" "$host"';
→ 拦截时状态码为403或444,$block_reason值即为具体拦截类型。 -
在 location 中触发拦截并写日志:
location / {<br> if ($block_reason != "none") { return 403; }<br> proxy_pass http://backend;<br> access_log /var/log/nginx/sec_access.log sec_log;<br> }
二、日志采集与解析:让拦截事件变成 Grafana 可用标签
无论用 Loki+Promtail、ELK 还是阿里云 SLS,都需提取 block_reason 作为独立 label 或 field:
-
Loki + Promtail:pipeline_stages 中加 regex 提取
block_reason,例如:- regex:<br> expression: 'block_reason="(?P<block_reason>[^"]+)"'<br> - labels:<br> block_reason</block_reason>
-
Filebeat + Logstash:grok filter 匹配
"block_reason":"%{DATA:block_reason}",再用 mutate 添加字段; -
阿里云 SLS:配置日志主题时开启“JSON 解析”,自动展开
block_reason字段供查询。
三、Grafana 大盘设计:聚焦攻击识别与响应效率
拦截日志大盘不是堆图表,而是回答三个问题:攻击从哪来?什么类型最多?是否绕过现有规则?
-
实时拦截趋势图:
Y 轴:count_over_time({job="nginx-sec"} |~ `block_reason="[^"]+"` [5m])
叠加线:按block_reason分组,快速识别突增类型(如某天scanner_ua暴涨)。 -
拦截来源 TOP10:
用client_ip或http_x_forwarded_for聚合,结合 GeoIP 显示攻击地理热力图;
对高频 IP 自动标注 C 段(192.168.1.*),辅助判断是否为 IDC 扫描器。 -
规则命中率分析表:
展示各block_reason类型的拦截次数占比(饼图)+ 时间分布(堆叠柱状图);
若file_ext_block占比超 70%,说明前端上传控制薄弱,需检查业务侧是否缺失校验。 -
误拦排查面板:
过滤条件:status == 403 and block_reason != "none",但http_user_agent是主流浏览器;
帮助发现因正则过宽导致的误杀(如把user-agent: sqlmap写成sql导致匹配正常请求)。
四、增强实用性的小技巧
让大盘真正服务运维和安全团队,而不是仅作展示:
- 添加 全局变量
$block_reason,支持下拉筛选特定拦截类型,联动所有图表; - 设置 403 错误率告警:
rate(nginx_http_responses_total{status="403"}[5m]) / rate(nginx_http_requests_total[5m]) > 0.05→ 触发后检查是否遭大规模扫描; - 对接企业微信/钉钉,告警消息中直接带出最近 3 条拦截原始日志(含
request_uri和http_user_agent),缩短研判时间。











