关键不是等工具报警,而是看请求本身是否“不像人”——同一ip在60秒内扫30个路径、ua写着sqlmap/2.0.1、head请求堆满404、error.log反复出现open() failed (2: no such file or directory),这些就是扫描器留下的硬痕迹。

直接从 Nginx 日志里识别攻击者扫描指纹,关键不是等工具报警,而是看请求本身是否“不像人”——同一 IP 在 60 秒内扫 30 个路径、UA 写着 sqlmap/2.0.1、HEAD 请求堆满 404、error.log 里反复出现 open() failed (2: No such file or directory),这些就是扫描器留下的硬痕迹。
盯紧 User-Agent 和空 UA 组合
很多扫描器会明目张胆暴露自己:
- sqlmap/2.0.1、Nikto/2.5.0、WhatWeb/2.1.1 这类带工具名和版本号的 UA,基本可直接判定
- 空 UA(日志中显示为
-)或极简 UA(如curl/7.81.0、python-requests/2.28.1),配合大量非常规路径访问,风险极高 - 正常浏览器 UA(如 Chrome/124)若集中出现在大量 404 请求中,且 Referer 全为空、Accept-Language 固定为 en-US,也要怀疑是伪造
抓取高频异常路径与状态码模式
真实用户不会连续请求 20 个不存在的路径,但扫描器会:
- 批量探测敏感路径:
/.git/config、/phpmyadmin/、/wp-config.php.bak、/backup.zip - 大量 404 集中在同一 IP + 同一时间窗口(如 1 分钟内超 20 次),且路径无业务关联性
- 响应体长度恒为 0 或极小(
$body_bytes_sent字段值多为 0),说明没加载页面内容,只是探路
从 error.log 中挖出铁证级线索
access.log 可被重写或跳转干扰,但 error.log 里的文件系统错误无法绕过:
- 典型日志条目:
[error] open() "/www/site/public/.env" failed (2: No such file or directory), client: 192.168.32.11 - 搜索关键词:
grep -i '\.git\|\.env\|phpmyadmin\|backup\.' /var/log/nginx/error.log - 统计最猛的 IP:
awk '/No such file/ && /(\.git|\.env)/ {print $12}' /var/log/nginx/error.log | sort | uniq -c | sort -nr | head -10
识别非人节奏与协议层异常
人类有停顿、跳转、等待渲染;扫描器只讲效率:
- 同一 IP 在 1 秒内发出 10+ 请求,间隔稳定在整数毫秒(如 123ms、200ms)
- 大量 HEAD 或 OPTIONS 请求(浏览器极少批量发 HEAD)
- 高频出现 499 状态码(客户端主动断连)、超短响应时间(
$request_time )、无 Cookie 或 Cookie 值全是 32 位随机字符串











