nginx日志分析需显式配置$request_length、$request_time、$upstream_response_time和$http_x_forwarded_for等关键字段,结合$remote_addr、$request、$status、$http_user_agent等组合识别sql注入、目录爆破、暴力破解及cc攻击等行为,并协同access_log与error_log实现闭环分析。

直接从 Nginx 日志格式入手分析攻击,核心是让日志“说话”——不是等出事再翻,而是提前把关键字段显式记录下来,让异常行为一目了然。重点不在堆砌字段,而在选对字段、设好阈值、配合上下文快速定位。
必须显式加入的几个关键字段
默认 combined 格式漏掉了多个攻击识别强相关字段。建议在 log_format 中至少补充以下三项:
- $request_length:整条请求原始字节数(含 header + body),POST 攻击、恶意填充、大 payload 都会在这里暴露。例如单次请求超 1MB,但业务接口根本不需上传文件,就高度可疑。
-
$request_time 和 $upstream_response_time:区分是客户端发包慢、Nginx 缓冲堆积,还是后端真正卡住。比如
$request_time很大但$upstream_response_time极小,可能是慢速攻击(如 Slowloris)。 -
$http_x_forwarded_for:避免代理或 CDN 后丢失真实源 IP。尤其当
$remote_addr是内网地址(如 10.x.x.x)时,靠它还原攻击者真实出口。
按攻击类型匹配日志字段组合
不同攻击会在不同字段留下“指纹”,单看一个字段容易误判,组合判断更可靠:
-
SQL 注入 / XSS 扫描:
$request中含union select、<script></script>、javascript:等关键字;同时状态码常为404或500;$http_user_agent可能为空或极简(如python-requests/2.28)。 -
目录爆破 / 敏感路径探测:大量
404响应集中在同一 IP;$request_uri高频访问/phpmyadmin、/wp-login.php、/admin等非业务路径;时间分布均匀(每秒 1–2 次),不像人工点击。 -
暴力破解登录:
$request_uri集中在/login、/auth等路径;$status大量为401或403;$request_method多为POST;$http_referer常为空或与站点无关。 -
DDoS / CC 攻击:
$remote_addr单 IP 分钟级请求数超 50–100;前 10 名 IP 总请求占当日总量 >60%;$time_local显示脉冲式高峰(如某分钟突增 10 倍);$request_uri和$status高度集中(全打/返回200或全扫/api返回404)。
用命令快速验证异常模式
不依赖复杂平台,日常巡检靠几条 awk/grep 就能发现苗头:
- 查超长 POST:
awk '$6=="POST" && $12>1048576 {print $1,$7,$12}' /var/log/nginx/access.log(假设$request_length是第 12 列) - 找高频 404 IP:
awk '$9==404 {ip[$1]++} END {for (i in ip) if (ip[i]>50) print i, ip[i]}' /var/log/nginx/access.log - 筛可疑 UA:
grep -Ei "(sqlmap|nuclei|gobuster|masscan|curl.*-s)" /var/log/nginx/access.log | head -10 - 看异常时间分布:
awk '{print substr($4,2,15)}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10
注意 error_log 的协同价值
access_log 记行为,error_log 记结果。两者结合才能闭环:
- 当
access_log出现大量413 Request Entity Too Large,去error_log查是否因client_max_body_size被触发——说明攻击者在试探边界。 -
access_log里某 IP 频繁500,error_log对应时间点若出现PHP Parse error或Segmentation fault,大概率是漏洞利用而非配置问题。 -
access_log中$http_x_forwarded_for为私有地址(如192.168.1.100),但error_log报connect() failed (111: Connection refused),可能说明攻击者伪造了 XFF。











