应优先通过行为模式(高频请求、无referer、固定路径、404集中、ua异常)识别恶意爬虫,再结合fail2ban自定义规则精准封禁,避免误伤;mod_evasive因规则僵化、不可审计,稳定性不如fail2ban。

怎么从 access.log 里快速识别恶意爬虫
Apache 默认的 access.log 里藏着大量线索,但直接 grep User-Agent 很容易漏掉伪装成浏览器的爬虫,或者被 UA 字段绕过。真正有效的识别点是行为模式:高频、无 referer、固定路径、404 集中、User-Agent 空或含明显机器人关键词(如 python-requests、curl/7.、Go-http-client)。
实操建议:
- 用
awk提取每小时请求数超过 500 的 IP:awk '{print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -nr | head -20 - 过滤出无
Referer且状态码为200或404的请求:awk '$11 == "-" && ($9 == "200" || $9 == "404") {print $1, $7, $9, $12}' /var/log/apache2/access.log | head -10 - 注意:日志格式必须含
%{Referer}i和%{User-Agent}i,否则$11、$12位置会错位
fail2ban 怎么精准匹配 Apache 日志里的异常行为
fail2ban 默认的 apache-badbots 规则太宽泛,容易误封正常爬虫(比如搜索引擎),也抓不住自定义路径扫描。关键在自定义 filter 中的正则是否锚定真实攻击特征。
实操建议:
- 新建
/etc/fail2ban/filter.d/apache-scan.conf,匹配路径爆破行为:[Definition] failregex = ^<host> -.*"(GET|POST) /(wp-admin|phpmyadmin|admin|shell|\.env) HTTP.*$ ignoreregex =</host>
- 在
jail.local中启用并限制频次:[apache-scan] enabled = true filter = apache-scan logpath = /var/log/apache2/access.log maxretry = 3 findtime = 600 bantime = 3600
- 注意:
failregex中的<host></host>是 fail2ban 内置变量,不能写成\d+\.\d+\.\d+\.\d+;路径区分大小写,wp-admin不会匹配WP-ADMIN
封禁 IP 后怎么验证没误伤、也没漏封
封禁后最常出问题的是:CDN 回源 IP 被封(导致全站 403)、Cloudflare 真实 IP 没传过来、或者 fail2ban 用 iptables 封了但 Apache 还在记录日志,造成二次触发。
实操建议:
- 检查是否拿到真实 IP:
tail -n 100 /var/log/apache2/access.log | head -5,确认第一列是不是你预期的客户端 IP,不是 CDN 节点 IP - 查当前封禁列表:
fail2ban-client status apache-scan
- 手动解封测试 IP:
fail2ban-client set apache-scan unbanip 192.168.1.100
- 注意:如果用了 Nginx 前置代理,Apache 日志中
%h必须替换成%{X-Forwarded-For}i,否则所有请求都显示为 127.0.0.1
为什么用 mod_evasive 不如 fail2ban 稳定
mod_evasive 是 Apache 模块级限流,响应快但规则硬编码、不持久、无法联动外部系统。一旦触发就直接返回 403,连日志都不留完整上下文,调试困难;而且它对慢速扫描(比如每分钟 10 次)完全无效。
实操建议:
- 除非你明确需要 sub-second 级响应(比如防 CC),否则优先用 fail2ban —— 它基于日志,可回溯、可审计、支持多日志源聚合
- 如果非要上
mod_evasive,务必关掉DOSSystemCommand(避免 fork 大量 shell 进程),改用DOSSystemCommand "echo %s | logger -t evasive"记日志再交由 fail2ban 处理 - 注意:
mod_evasive的DOSEmailNotify在高并发下会阻塞 Apache 子进程,生产环境慎用
日志分析这事,最难的不是写正则,而是搞清你的业务哪类请求算“异常”——比如电商站扫商品 ID 是正常行为,但扫后台接口就是风险;同一个 IP,白天刷首页和凌晨扫 /api/user 接口,意义完全不同。别迷信自动封禁,先跑一周日志聚类,再决定阈值。










