核心是让日志能说话——通过结构化记录、关键路径分离、轻量分析和自动联动,将原始日志转化为可过滤、可统计、可响应的安全信号。

核心是让日志能说话——不是堆砌字段,而是把“谁、干了什么、是否可疑”变成可过滤、可统计、可联动的结构化信号。
一、记录阶段:用结构化格式打牢审计基础
默认日志太简略,无法支撑安全分析。必须自定义 log_format,重点注入四类字段:
- 真实客户端 IP:用 $realip_remote_addr(配合 set_real_ip_from)替代 $remote_addr,避免代理或 CDN 掩盖攻击源
-
请求意图标识:用 map 指令标记高危行为,例如:
map "$request_method:$uri" $is_admin {
~^(GET|POST|PUT|DELETE):/admin/|/sys/|/api/v1/(users|roles) 1;
default 0;
} - 目标资源指纹:对含 ID 的路径(如 /api/v1/users/123),提取数字部分作为 $target_id;对登录、密码重置等操作,用 $arg_username 或 $arg_email 记录参数名(不记明文值)
-
JSON 格式输出:便于下游工具解析,例如:
log_format json '{ "@timestamp": "$time_iso8601", "clientip": "$realip_remote_addr", "method": "$request_method", "uri": "$uri", "status": $status, "ua": "$http_user_agent", "referer": "$http_referer", "is_admin": $is_admin, "target_id": "$target_id" }';
access_log /var/log/nginx/access.json json;
二、聚焦关键路径:分离后台与敏感接口日志
把管理接口、API、登录页等高风险流量单独记录,避免混在海量普通请求中被淹没:
- 在对应 location 块中启用条件日志,例如:
location ^~ /admin/ {
access_log /var/log/nginx/admin.log json if=$is_admin;
} - 对 /api/v1/users/(\d+) 这类路径,用正则捕获 ID 并写入 $target_id,再通过 if=$is_admin 控制是否落盘
- 日志文件权限设为 640,属主 nginx:audit,限制读取范围
三、分析阶段:用轻量命令快速定位异常模式
无需立即上 ELK,日常巡检靠几条命令就能发现多数问题:
-
高频探测 IP:统计 1 分钟内访问 404 超 50 次的 IP
awk -v d="$(date -d '1 minute ago' +'%d/%b/%Y:%H:%M')"' '$4 > "["d {print $1}' /var/log/nginx/access.json | sort | uniq -c | sort -nr | head -10 -
越权访问线索:同一用户($http_x_user_id)短时间内访问多个无业务关联的 $target_id
awk '$12 ~ /user_id=[^&]+/ && $13 ~ /target_id=[0-9]+/ {print $1,$12,$13}' /var/log/nginx/admin.log | sort | uniq -c | sort -nr | head -20 - 恶意 UA 或路径特征:grep 匹配 sqlmap、nuclei、union select、<script>、../ 等关键词,结合状态码(如 403+500)提高准确率</script>
四、联动响应:从识别到封禁的闭环
日志本身不封 IP,但它是自动响应的触发器:
- 用 fail2ban 监控 admin.log,匹配到 $is_admin == 1 且 status == 403 时自动调用 iptables 封禁
- 将 JSON 日志接入 Loki + Grafana,配置告警规则:过去 5 分钟内同一 clientip 触发 is_admin=1 且 status=500 ≥ 3 次 → 发送企业微信告警
- 对接云防火墙 API:当日志分析平台识别出扫描团伙(如 10 个 IP 共同访问 /wp-admin/),批量推送 IP 列表至 WAF 黑名单











