📌 第六部分:自动封锁恶意IP地址
👀 为什么需要 Fail2ban?
WordPress 是世界上最受欢迎的建站系统,也正因为它的普及度,使得它成为攻击者最常扫描和攻击的目标之一:
- 无休止的暴力破解尝试(尤其针对
/wp-login.php
和 XML-RPC 接口); - 利用已知插件/主题漏洞的攻击;
- 针对
/wp-admin/
发起的探测与扫描; - 利用代理池发起高频、短周期、分布式攻击,避开传统阈值限制。
我们前面已经讲过如何收集和聚合 WordPress 的访问日志,也初步探讨了如何通过日志监控(如Loki+Grafana)进行趋势预警。但日志只是“被攻击的记录”,Fail2ban 的作用则是“在攻击进行中及时反制” —— 它是一位“日志驱动的防暴警察”。
⚙️ Fail2ban 在防御体系中的作用
Fail2ban 是一个轻量级的入侵防御系统,它通过分析日志文件,寻找可疑行为(比如多次失败的登录),并自动封锁对应的 IP 地址。
它的优势包括:
- 自动响应攻击:根据日志触发封禁,无需人工介入。
- 极低的资源占用:相比复杂的WAF或安全审计系统,Fail2ban使用Python编写,运行轻巧,适合部署在中小型站点。
- 高度可定制:规则灵活,既可以防SSH、FTP,也可以配合nginx、Postfix、ModSecurity等服务。
- 与日志监控系统联动:可与日志聚合(如 rsyslog、journald)和 Grafana 报警集成,提升可观测性。
- 有效降低“扫站”成功率”:短时间内高频恶意访问者将被及时踢出,保护服务稳定性。
一句话总结:Fail2ban是对“日志→监控”链条的“动作响应”延伸,让监控真正能反击。
🧠 Fail2ban 的工作原理(通俗解释)
Fail2ban 的逻辑可以总结为三句话:
它看日志 —— 发现攻击 —— 自动封禁。
更具体点:
- 监控日志文件(比如
/var/log/nginx/error.log
); - 使用正则表达式匹配特定行为(比如 5 分钟内连续失败登录 3 次);
- 触发动作(比如使用
iptables
或firewalld
临时封禁 IP); - 一定时间后自动解封(或者永久封禁,依据设置);
举个例子:
- 某 IP 在 60 秒内尝试登录 WordPress 后台失败了 5 次;
- Fail2ban 从 nginx 或 WordPress 的日志中看到了这些失败;
- 于是它调用系统命令把这个 IP 加入封禁列表,拒绝其后续所有访问请求。
🛠️ 安装 Fail2ban 的大致流程
Fail2ban 是主流 Linux 系统的软件仓库中提供的开源工具,安装和启用过程较为简单:
- 安装软件包
- 启动并设置开机启动
- 配置规则(jail)
Fail2ban 的规则配置通常位于 /etc/fail2ban/jail.d/
,你可以为每个服务(如 nginx、wordpress、postfix)写一个单独的监控规则(jail)文件。
💡 如何使用 Fail2ban 保护 WordPress
Fail2ban 本身不内置针对 WordPress 的规则,但结合 nginx 或 apache 日志,可以构建出精准的防护措施。例如:
- 封禁高频访问
/wp-login.php
的 IP; - 封禁频繁探测
/wp-admin/
、xmlrpc.php
的行为; - 配合 ModSecurity 或自定义 WAF 规则输出的日志,自动封禁触发规则的来源 IP;
这些都是 Fail2ban 能做、且自动完成的事情。
🧭 Fail2ban 的一些常见命令(快速参考)
# 查看当前哪些规则正在运行
$ sudo fail2ban-client status
# 查看某个 jail 的详细状态(比如 nginx-wp-login)
$ sudo fail2ban-client status nginx-wp-login
# 手动封禁一个 IP
$ sudo fail2ban-client set nginx-wp-login banip 1.2.3.4
# 解除封禁
$ sudo fail2ban-client set nginx-wp-login unbanip 1.2.3.4
# 重启 Fail2ban 服务(例如修改配置后)
$ sudo systemctl restart fail2ban
🛡️ Fail2ban 是“站点防御的护城河”
Fail2ban 是连接日志分析与主动防御之间的那一环,它不是“万能盾牌”,但它的“快速反应”能力,能有效击退那些一眼就能识别的恶意行为。对于像 WordPress 这样常年处于暴露状态的系统来说,Fail2ban 是你最容易上手、成本最低、效果可见的安全增强工具之一。
站点能被打,不该是因为我们没看到,而是因为我们没反应。Fail2ban,就是那个帮你第一时间“反应”的战士。
安装fail2ban
启用epel仓库
$ sudo dnf config-manager --set-enabled epel
安装fail2ban并设置为开机启动
$ sudo dnf install fail2ban
$ sudo systemctl enable --now fail2ban
配置过滤器
下面是使用 Fail2ban 过滤 WordPress 登录失败行为(例如 /wp-login.php
)并封禁恶意 IP 的完整配置步骤。
目标:在 5 分钟内连续尝试登录失败的 IP 被封禁 48 小时。
✅ 步骤一:创建自定义 Filter(过滤器)
Fail2ban 的过滤器定义了从日志中匹配哪些“恶意行为”的规则。
假设你使用 nginx
,日志路径是 /var/log/nginx/access.log
,我们要匹配 URL 请求 /wp-login.php
并返回码是 401
(或其他登录失败码,比如 200
+ 登录失败关键词)。
创建过滤器文件
$ sudo vim /etc/fail2ban/filter.d/wp-login.conf
示例内容(匹配 wp-login.php
请求且返回码为401):
[Definition]
failregex = ^<HOST> -.*"(GET|POST) /wp-login\.php.*" 401
ignoreregex =
参数解释:
项目 | 说明 |
---|---|
failregex | 正则表达式,定义失败行为。<HOST> 会被自动替换为 IP 地址。 |
ignoreregex | 可选,用于忽略某些匹配,通常为空。 |
✅ 步骤二:创建 Jail(监狱规则)
Jail 定义了启用哪个过滤器,监控哪个日志,什么时间段触发多少次,封禁多久等。
编辑主配置文件(推荐使用 override)
$ sudo vim /etc/fail2ban/jail.d/wp-login.local
示例配置:
[wp-login]
enabled = true
filter = wp-login
banaction = firewallcmd-ipset
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 300
bantime = 172800
port = http,https
参数解释:
参数 | 说明 |
---|---|
enabled | 是否启用该 jail,设为 true 开启。 |
filter | 指定要使用的过滤器(上一步创建的 wp-login )。 |
banaction | 封锁方式,这里使用 firewalld 来阻断 IP。你也可以改成 iptables , nftables 等。 |
logpath | 日志文件路径,确保此日志能记录访问行为。 |
maxretry | 允许的最大失败次数(这里为 5 次)。 |
findtime | 时间窗口(秒),这里为 300 秒即 5 分钟。 |
bantime | 封禁时间(秒),172800 秒即 48 小时。 |
port | 不允许被封禁的IP地址访问哪些端口。 |
✅ 步骤三:测试配置是否生效
你可以用以下命令测试 failregex 是否正确匹配日志:
$ sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/wp-login.conf
如果输出匹配的行数和 IP 正确,说明规则有效。
✅ 步骤四:重启 Fail2ban 服务
$ sudo systemctl restart fail2ban
✅ 步骤五:查看状态和已封 IP
# 查看 wp-login jail 状态
$ sudo fail2ban-client status wp-login
# 查看所有 jail 状态
$ sudo fail2ban-client status
🔍 拓展建议
- 更严格匹配:如你能确定 Nginx 日志格式,还可以加上 User-Agent 检查、POST 请求检查等。
- 加白名单:防止自己被封,可加入
/etc/fail2ban/jail.local
中的ignoreip = 127.0.0.1 <你的公网 IP>
。如果自己不小心被封了,那只能进入云服务器的后台终端解封。