你是否遇到过这种情况:
- 现象:你的WordPress博客突然变慢,甚至出现 502 Bad Gateway 错误。
- 排查 :登录服务器查看
top,发现 CPU 占用率飙升到 100%,PHP-FPM 进程多得吓人。 - 真相:查看 Nginx 或 Apache 的访问日志,发现并没有多少真实人类在看文章,反而是大量的机器人在疯狂抓取。
为什么资源会紧张? WordPress 是动态网站,每一次页面访问都需要 PHP 解析和 MySQL 查询。如果一个爬虫每秒发起 10 个请求,对于一台配置较低(如 1核2G)的 VPS 来说,这就足以让数据库崩溃。
除了 Google、Bing 这种带来流量的"好爬虫",互联网上充斥着大量无用爬虫:
- SEO工具爬虫(Ahrefs, Semrush, MJ12bot):对你没流量贡献,却疯狂消耗资源。
- 内容采集器:想把你的原创文章搬运走。
- bug扫描器 :疯狂探测
wp-login.php或xmlrpc.php。
今天,我们不装臃肿的防火墙插件,而是用 Python 这种轻量级武器,从日志中揪出这些"资源吸血鬼",并在服务器层面直接封杀。
🛠️ 第一步:获取作案证据(访问日志)
首先,你需要找到 Web 服务器的访问日志(Access Log)。 通常在 Linux 服务器上,路径如下:
- Nginx :
/var/log/nginx/access.log - Apache :
/var/log/apache2/access.log或/var/log/httpd/access_log
把这个文件下载到本地,或者直接在服务器上用 Python 处理。
🐍 第二步:Python 编写"爬虫侦探"脚本
我们将编写一个 Python 脚本,完成以下任务:
- 解析日志文件。
- 统计 IP 的访问频率。
- 统计 User-Agent(用户代理)的分布。
- 自动生成封禁名单。
核心代码:analyze_bot.py
python
import re
from collections import Counter
import csv
# --- 配置区域 ---
LOG_FILE = 'access.log' # 你的日志文件路径
THRESHOLD = 500 # 阈值:如果一个IP在日志中出现超过500次,视为可疑
OUTPUT_BAN_FILE = 'nginx_deny_list.conf' # 输出的封禁配置文件
# Nginx日志正则匹配模式 (根据你的日志格式调整,这是默认格式)
# 格式示例: 192.168.1.1 - - [23/Nov/2025:10:00:00 +0000] "GET / HTTP/1.1" 200 ...
LOG_PATTERN = re.compile(r'(?P<ip>\d+.\d+.\d+.\d+).*?"(?P<method>\w+) (?P<path>.*?) HTTP.*?" (?P<status>\d+) .*?"(?P<agent>.*?)"')
def analyze_logs():
ip_counter = Counter()
ua_counter = Counter()
suspicious_ips = {} # 存储 {ip: user_agent}
print(f"🔄 正在分析日志: {LOG_FILE} ...")
with open(LOG_FILE, 'r', encoding='utf-8', errors='ignore') as f:
for line in f:
match = LOG_PATTERN.search(line)
if match:
data = match.groupdict()
ip = data['ip']
ua = data['agent']
# 统计IP和UA
ip_counter[ip] += 1
ua_counter[ua] += 1
# 记录最后一次该IP使用的UA,方便人工复核
suspicious_ips[ip] = ua
return ip_counter, ua_counter, suspicious_ips
def generate_report(ip_counts, ua_counts, suspicious_data):
print("\n--- 📊 访问量 Top 10 IP ---")
top_ips = ip_counts.most_common(10)
for ip, count in top_ips:
print(f"IP: {ip} | 次数: {count} | UA摘要: {suspicious_data[ip][:30]}...")
print("\n--- 🤖 访问量 Top 10 User-Agents ---")
for ua, count in ua_counts.most_common(10):
print(f"次数: {count} | UA: {ua}")
# 生成 Nginx 封禁列表
print(f"\n--- 🚫 生成封禁建议 (超过 {THRESHOLD} 次访问) ---")
banned_count = 0
with open(OUTPUT_BAN_FILE, 'w') as f:
f.write("# Auto-generated block list\n")
for ip, count in ip_counts.items():
if count > THRESHOLD:
# 排除本地回环
if ip.startswith('127.0.0'): continue
# 写入 Nginx 格式: deny 1.2.3.4;
f.write(f"deny {ip};\n")
banned_count += 1
print(f"✅ 已生成配置文件: {OUTPUT_BAN_FILE}")
print(f"🔨 建议封禁的 IP 数量: {banned_count}")
if __name__ == '__main__':
try:
ip_counts, ua_counts, suspicious_data = analyze_logs()
generate_report(ip_counts, ua_counts, suspicious_data)
except FileNotFoundError:
print("❌ 错误:找不到日志文件,请检查路径。")
🕵️ 第三步:案例分析与实战操作
假设你运行了上面的代码,得到以下输出结果,我们来分析几个典型场景。
场景 A:暴力的 IP 采集者
脚本输出:
yaml
IP: 45.132.xx.xx | 次数: 5000 | UA摘要: Python-urllib/3.8...
分析 :一个 IP 访问了 5000 次,User-Agent 竟然是 Python-urllib。这意味着有人在写简陋的脚本暴力抓取你的站,完全没有伪装。 对策 :直接封杀 IP。
场景 B:伪装成正常的 SEO 工具
脚本输出:
yaml
次数: 2000 | UA: Mozilla/5.0 (compatible; MJ12bot/v1.4.8; ...)
次数: 1500 | UA: Mozilla/5.0 (compatible; SemrushBot/7~bl; ...)
分析 :MJ12bot 和 SemrushBot 是著名的 SEO 分析工具。它们不是恶意ddos,但它们抓取频率极高,而且对普通博客来说,这类商业 SEO 数据的价值远低于它们消耗的服务器资源。 对策 :通过 User-Agent 屏蔽。
场景 C:恶意扫描
日志特征 : 脚本发现某个 IP 的 path 全是 /wp-login.php, .env, sql.bak 等。 分析 :这是在扫描bug,试图爆破后台。 对策 :立刻封杀,并安装 Fail2Ban 自动处理。
🛡️ 第四步:实施封锁
Python 帮我们找出了敌人,现在要在服务器层面进行拦截。
1. 基于 IP 的封禁 (Nginx)
Python 脚本已经生成了 nginx_deny_list.conf,内容大致如下:
ini
deny 45.132.11.22;
deny 103.21.33.44;
部署方法:
- 将该文件上传到 Nginx 配置目录(如
/etc/nginx/conf.d/)。 - 在你的网站配置文件(
server块内)引入它:
ini
server {
listen 80;
server_name example.com;
# 引入封禁列表
include /etc/nginx/conf.d/nginx_deny_list.conf;
location / {
...
}
}
- 重载 Nginx:
sudo nginx -s reload。 效果:这些 IP 访问时直接返回 403 Forbidden,甚至不消耗 PHP 资源。
2. 基于 User-Agent 的封禁 (Nginx)
针对那些换 IP 很勤快,但 UA 固定的爬虫(如 MJ12bot, AhrefsBot),直接在 Nginx 配置文件中添加判断:
bash
server {
# ... 其他配置
# 禁止特定的 User-Agent
if ($http_user_agent ~* (MJ12bot|AhrefsBot|SemrushBot|DotBot|PetalBot|Bytespider)) {
return 403;
}
}
注意: Bytespider 是字节跳动的爬虫,非常凶猛,如果是中文站且不需要今日头条的流量,建议限制或封禁。
🚀 进阶技巧:自动化防御 (Fail2Ban)
虽然 Python 脚本分析很有用,但手动跑太累。对于 WordPress,建议结合 Fail2Ban 实现自动化。
虽然 Fail2Ban 不是 Python 写的(虽然它现在也有 Python 绑定),但它的逻辑和我们上面的脚本一样:读日志 -> 正则匹配 -> 调用防火墙(iptables)封IP。
简单的 WordPress 防爆破配置思路:
- 安装 Fail2Ban。
- 配置 Jail 监控
/var/log/auth.log或 Nginx 日志。 - 规则:如果在 5 分钟内访问
wp-login.php返回非 200 状态码超过 5 次,封禁 IP 1小时。
对于资源紧张的 WordPress 博客:
- 定期分析:使用提供的 Python 脚本定期(如每周)"体检",看看到底是谁在消耗你的 CPU。
- 狠心做减法:对于不带来直接流量的国外 SEO 爬虫(Ahrefs, MJ12等),建议直接在 Nginx 层屏蔽 User-Agent。
- 精确打击:对于异常高频的单个 IP,利用 Python 生成的黑名单直接 Deny。
通过这套组合拳,你会发现服务器负载会瞬间下降,博客又能秒开了!