强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

CDN 与 WAF 精讲教程 / 第13章 日志与分析

第13章 日志与分析

安全防护的最后也是最关键的一环:日志分析。没有完善的日志收集、分析和告警体系,WAF 形同虚设。本章讲解 CDN/WAF 日志的收集、分析和安全审计实践。


13.1 日志体系架构

13.1.1 日志收集架构

日志收集与分析架构:

┌─────────────────────────────────────────────────────────────────┐
│  日志来源                                                       │
│  ├── CDN 边缘日志 (Nginx / Cloudflare Logs)                    │
│  ├── WAF 审计日志 (ModSecurity / 自定义 WAF)                    │
│  ├── 应用访问日志 (App Access Log)                              │
│  ├── 应用错误日志 (App Error Log)                               │
│  ├── 系统日志 (syslog / journald)                               │
│  └── 数据库审计日志 (MySQL Audit / pgAudit)                     │
└──────────────────────────┬──────────────────────────────────────┘
                           │
┌──────────────────────────▼──────────────────────────────────────┐
│  日志传输层                                                     │
│  ├── Filebeat / Fluentd / Vector / Promtail                    │
│  ├── Kafka (缓冲层,可选)                                       │
│  └── 直连 Elasticsearch / Loki                                 │
└──────────────────────────┬──────────────────────────────────────┘
                           │
┌──────────────────────────▼──────────────────────────────────────┐
│  存储与索引                                                     │
│  ├── Elasticsearch (全文索引,结构化查询)                        │
│  ├── Loki (标签索引,轻量级)                                    │
│  └── ClickHouse (列式存储,大数据量)                            │
└──────────────────────────┬──────────────────────────────────────┘
                           │
┌──────────────────────────▼──────────────────────────────────────┐
│  分析与可视化                                                    │
│  ├── Kibana (Elasticsearch 生态)                                │
│  ├── Grafana (Loki / Prometheus 生态)                           │
│  └── 自定义仪表盘                                               │
└──────────────────────────┬──────────────────────────────────────┘
                           │
┌──────────────────────────▼──────────────────────────────────────┐
│  告警与响应                                                     │
│  ├── 邮件 / 短信 / 企业微信 / 钉钉                               │
│  ├── PagerDuty / OpsGenie (On-Call)                             │
│  └── SOAR (安全编排自动化响应)                                   │
└─────────────────────────────────────────────────────────────────┘

13.2 日志格式标准

13.2.1 WAF 日志字段

字段类型说明示例
timestampdatetime请求时间2026-05-10T12:00:00Z
client_ipstring客户端 IP203.0.113.50
methodstringHTTP 方法GET
uristring请求路径/api/users?id=1'
statusint响应状态码403
user_agentstringUAsqlmap/1.0
rule_idstring触发规则 ID942100
rule_msgstring规则描述SQL Injection Attack
severitystring严重级别CRITICAL
actionstring处置动作BLOCK
anomaly_scoreint异常评分10
request_bodystring请求体(encoded)
response_timeint响应耗时 (ms)5

13.2.2 Nginx JSON 日志格式

# Nginx JSON 日志格式
log_format json_combined escape=json
'{'
    '"timestamp":"$time_iso8601",'
    '"remote_addr":"$remote_addr",'
    '"request_method":"$request_method",'
    '"request_uri":"$request_uri",'
    '"status":$status,'
    '"body_bytes_sent":$body_bytes_sent,'
    '"request_time":$request_time,'
    '"http_referer":"$http_referer",'
    '"http_user_agent":"$http_user_agent",'
    '"http_x_forwarded_for":"$http_x_forwarded_for",'
    '"upstream_addr":"$upstream_addr",'
    '"upstream_response_time":"$upstream_response_time",'
    '"ssl_protocol":"$ssl_protocol",'
    '"ssl_cipher":"$ssl_cipher"'
'}';

access_log /var/log/nginx/access.json json_combined;

13.2.3 ModSecurity 审计日志

--a]--
[10/May/2026:12:00:00 +0800] 1715347200 203.0.113.50 54321 192.0.2.1 443
--A]--
GET /api/users?id=1%27+UNION+SELECT+*+FROM+users-- HTTP/1.1
Host: example.com
User-Agent: sqlmap/1.0
Accept: */*

--B]--
HTTP/1.1 403 Forbidden

--H]--
Message: Warning. detected SQLi using libinj. [file "/etc/nginx/modsecurity/crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf"] [line "42"] [id "942100"] [msg "SQL Injection Attack Detected via libinj"] [data "Matched Data: UNION SELECT found within ARGS:id: 1' UNION SELECT * FROM users--"] [severity "CRITICAL"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-sqli"] [tag "OWASP_CRS"] [tag "paranoia-level/1"]
Action: Intercepted (phase 2)
--Z]--

13.3 ELK 部署

13.3.1 Docker Compose 快速部署

# docker-compose.yml - ELK + Filebeat

version: '3.8'

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=true
      - ELASTIC_PASSWORD=changeme
      - "ES_JAVA_OPTS=-Xms2g -Xmx2g"
    volumes:
      - es_data:/usr/share/elasticsearch/data
    ports:
      - "9200:9200"
    networks:
      - elk
    healthcheck:
      test: ["CMD-SHELL", "curl -s http://localhost:9200/_cluster/health | grep -q '\"status\":\"green\"\\|\"status\":\"yellow\"'"]
      interval: 10s
      timeout: 5s
      retries: 5

  kibana:
    image: docker.elastic.co/kibana/kibana:8.12.0
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
      - ELASTICSEARCH_USERNAME=kibana_system
      - ELASTICSEARCH_PASSWORD=changeme
    ports:
      - "5601:5601"
    networks:
      - elk
    depends_on:
      elasticsearch:
        condition: service_healthy

  filebeat:
    image: docker.elastic.co/beats/filebeat:8.12.0
    user: root
    volumes:
      - ./filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
      - /var/log/nginx:/var/log/nginx:ro
      - /var/log/modsecurity:/var/log/modsecurity:ro
      - filebeat_data:/usr/share/filebeat/data
    networks:
      - elk
    depends_on:
      elasticsearch:
        condition: service_healthy

volumes:
  es_data:
  filebeat_data:

networks:
  elk:
    driver: bridge

13.3.2 Filebeat 配置

# filebeat.yml

filebeat.inputs:
  # Nginx JSON 日志
  - type: filestream
    paths:
      - /var/log/nginx/access.json
    parsers:
      - ndjson:
          target: ""
          add_error_key: true
    fields:
      log_type: nginx_access
    fields_under_root: true

  # ModSecurity 审计日志
  - type: filestream
    paths:
      - /var/log/modsecurity/modsec_audit.log
    parsers:
      - multiline:
          pattern: '^\-\-'
          negate: true
          match: after
    fields:
      log_type: modsecurity
    fields_under_root: true

output.elasticsearch:
  hosts: ["http://elasticsearch:9200"]
  username: "elastic"
  password: "changeme"
  index: "waf-logs-%{+yyyy.MM.dd}"

setup.template:
  name: "waf-logs"
  pattern: "waf-logs-*"

setup.ilm.enabled: false

13.4 攻击检测分析

13.4.1 KQL 查询示例

# Kibana KQL 查询示例

# 1. 查询所有被拦截的 SQL 注入攻击
rule_id: "942*" AND action: "BLOCK"

# 2. 查询特定 IP 的攻击记录
client_ip: "203.0.113.50"

# 3. 查询过去 1 小时的攻击 Top 10 IP
# (使用 Kibana Visualization → Top 10 → Terms Aggregation → client_ip)

# 4. 查询 XSS 攻击
uri: "<script" OR uri: "javascript:" OR uri: "onerror"

# 5. 查询可疑爬虫
user_agent: ("sqlmap" OR "nikto" OR "nmap" OR "masscan")

# 6. 查询 403 响应
status: 403

# 7. 查询慢请求 (超过 5 秒)
request_time: >5

13.4.2 攻击统计仪表盘

Kibana 安全仪表盘设计:

┌──────────────────────────────────────────────────────────────┐
│  安全概览仪表盘                                               │
│                                                              │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────────────┐│
│  │ 总请求数      │  │ 攻击拦截数    │  │ 拦截率              ││
│  │ 1,234,567    │  │ 12,345       │  │ 1.0%               ││
│  └──────────────┘  └──────────────┘  └──────────────────────┘│
│                                                              │
│  ┌──────────────────────────────────────────────────────────┐│
│  │ 攻击趋势图 (时间序列)                                     ││
│  │ [====攻击量折线图====]                                    ││
│  └──────────────────────────────────────────────────────────┘│
│                                                              │
│  ┌─────────────────────┐  ┌──────────────────────────────────┐│
│  │ 攻击类型分布 (饼图)  │  │ Top 10 攻击 IP (柱状图)          ││
│  │ SQLi: 45%           │  │ 1. 203.0.113.50  (2,345)        ││
│  │ XSS: 30%            │  │ 2. 198.51.100.10 (1,234)        ││
│  │ RCE: 10%            │  │ 3. 192.0.2.99    (987)          ││
│  │ Other: 15%          │  │                                  ││
│  └─────────────────────┘  └──────────────────────────────────┘│
│                                                              │
│  ┌──────────────────────────────────────────────────────────┐│
│  │ 最近攻击日志 (表格)                                       ││
│  │ 时间 | IP | 规则 | URI | 动作                            ││
│  │ ...                                                      ││
│  └──────────────────────────────────────────────────────────┘│
└──────────────────────────────────────────────────────────────┘

13.5 实时告警

13.5.1 告警规则设计

告警级别条件响应时间通知方式
P0 紧急大规模 DDoS / 数据泄露5 分钟电话 + 短信
P1 严重WAF 高频拦截(>100/min)15 分钟短信 + 企业微信
P2 警告可疑 IP 反复触发规则1 小时企业微信
P3 信息新攻击模式出现24 小时邮件

13.5.2 ElastAlert 告警规则

# elastalert_rules/high_frequency_attack.yaml

name: "高频攻击告警"
type: frequency
index: waf-logs-*

# 条件:5 分钟内同 IP 攻击超过 50 次
num_events: 50
timeframe:
  minutes: 5

filter:
  - term:
      action: "BLOCK"

query_key: client_ip

alert:
  - "email"
  - "slack"

email:
  - "security@example.com"

slack:
  slack_webhook_url: "https://hooks.slack.com/services/xxx"
  slack_channel: "#security-alerts"
  slack_username: "WAF Alert"

alert_text: |
  ⚠️ 高频攻击告警
  攻击 IP: {0}
  5 分钟内拦截次数: {1}
  最近攻击规则: {2}
  时间: {3}

alert_text_args:
  - client_ip
  - num_hits
  - rule_msg
  - timestamp

13.6 安全审计

13.6.1 审计日志保留策略

日志类型保留周期存储位置合规要求
WAF 审计日志90 天热 + 1 年冷ES + S3/OSS等保 2.0
CDN 访问日志30 天热 + 6 个月冷ES + 对象存储
系统日志6 个月ES + 归档等保 2.0
数据库审计1 年专用存储等保/PCI DSS

13.6.2 等保 2.0 日志要求

等保 2.0 (GB/T 22239-2019) 日志要求:

  ├── 应当记录:
  │   ├── 用户登录/登出日志
  │   ├── 重要操作行为日志
  │   ├── 安全事件日志
  │   ├── 异常访问日志
  │   └── 管理员操作日志
  │
  ├── 日志内容:
  │   ├── 事件日期和时间
  │   ├── 用户标识
  │   ├── 事件类型
  │   ├── 事件是否成功
  │   └── 其他与审计相关的信息
  │
  └── 保留要求:
      ├── 保存时间 ≥ 6 个月(三级等保)
      └── 定期备份,防止篡改/丢失

13.7 注意事项

⚠️ 日志量控制:WAF 日志量巨大。建议只记录被拦截的请求和可疑请求,正常请求使用采样记录。

⚠️ 敏感信息脱敏:日志中的请求体可能包含密码、信用卡号等敏感信息,需在采集时脱敏。

⚠️ 日志完整性:防止日志被篡改。建议开启日志签名或使用 WORM(Write Once Read Many)存储。

⚠️ 性能影响:高频日志写入可能影响 WAF 性能。建议使用异步日志写入。


13.8 扩展阅读


本章小结

主题核心要点
架构来源 → 传输 (Filebeat) → 存储 (ES) → 可视化 (Kibana)
日志格式JSON 结构化,包含 rule_id/severity/action
攻击分析KQL 查询 + 仪表盘 + Top N 分析
实时告警ElastAlert/Watcher 按频率/阈值触发
审计合规等保 2.0 要求 ≥ 6 个月保留

下一章:第14章 Docker 部署 →