fail2ban 进阶:从安装到自定义规则
fail2ban 不只是装上就行。小够带你从安装、jail.local 配置讲到自定义过滤规则、recidive 累犯封禁和邮件告警:让爆破者在第一次试探后就被请出门,惯犯直接拉黑更久,异常情况第一时间通知到你。
我是小够。之前讲过 fail2ban 能自动封禁爆破 IP,那是入门版。今天讲进阶:默认配置其实很保守,调一调才能真正发挥作用。先说原理,一句话:fail2ban 盯着日志文件,发现某个 IP 在短时间内失败次数超标,就调用防火墙把它封一段时间。盯日志 + 调防火墙,就这么简单。
安装与基础配置
sudo apt install fail2ban -y
sudo systemctl enable --now fail2ban
千万别直接改 jail.conf,升级会被覆盖。正确做法是新建 /etc/fail2ban/jail.local,只写你要覆盖的项:
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3
banaction = ufw
意思是:10 分钟内失败 3 次,封 1 小时。用 ufw 做封禁动作,和你系统防火墙是同一套,不打架。
SSH 的 jail 开到最严
[sshd]
enabled = true
port = 2222
maxretry = 3
bantime = 86400
注意 port 要和你实际的 SSH 端口一致,不然规则对不上。SSH 这种关键服务,封禁时间给到 24 小时不过分——正常人输错 3 次密码的情况极少。
recidive:专治累犯
有些 IP 被放出来后继续扫,recidive jail 就是干这个的:它盯的是 fail2ban 自己的日志,统计"被封过 N 次"的 IP,直接封更久:
[recidive]
enabled = true
bantime = 604800
findtime = 86400
maxretry = 3
一周内被封 3 次的,直接拉黑 7 天。对付顽固扫描器特别有效。
自定义过滤规则
默认规则只认识标准日志格式。如果你跑了面板或改了日志格式,可以自己写 filter。文件放在 /etc/fail2ban/filter.d/,比如针对某个 Web 应用的登录接口:
[Definition]
failregex = ^.*登录失败.*IP=<HOST>.*$
ignoreregex =
<HOST> 是占位符,fail2ban 会自动提取 IP。写完用 fail2ban-regex 测试:
fail2ban-regex /var/log/myapp.log /etc/fail2ban/filter.d/myapp.conf
能正确匹配到失败行再启用,别凭感觉上线。
邮件告警:出事第一时间知道
[DEFAULT]
destemail = 你的邮箱
sender = fail2ban@你的域名
action = %(action_mwl)s
action_mwl 表示封禁时发邮件并附带相关日志片段。IP 被封是常态,邮件太多会麻木——建议只给 sshd 这类关键 jail 开告警,或者把阈值调高。
一份可直接用的 jail.local
把前面讲的拼起来,一份完整的 /etc/fail2ban/jail.local 参考:
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3
banaction = ufw
ignoreip = 127.0.0.1/8 你的家庭IP
destemail = 你的邮箱
sender = fail2ban@你的域名
[sshd]
enabled = true
port = 2222
maxretry = 3
bantime = 86400
[recidive]
enabled = true
bantime = 604800
findtime = 86400
maxretry = 3
按你自己的端口和 IP 改完,sudo systemctl restart fail2ban,再用 fail2ban-client status 确认 jail 都起来了。
保护 Web 面板登录
面板(宝塔/1Panel)的登录页也是爆破目标。思路一样:找到面板的登录失败日志,写 filter,配 jail。以 1Panel 为例,它的登录日志里有失败记录,filter 大致这样:
[Definition]
failregex = ^.*login failed.*from <HOST>.*$
ignoreregex =
具体日志格式以你装的版本为准,先用 fail2ban-regex 验证匹配再上线。面板被爆破的危害比 SSH 更大(面板权限通常是 root 级),值得单独配一个 jail,封禁时间给长一点。
用了 CDN,看到的 IP 全是 CDN 的怎么办
这是个经典坑:网站套了 CDN 后,Nginx 日志里记录的 IP 是 CDN 节点的,不是真实攻击者 IP。fail2ban 按这个 IP 封,封的是 CDN——轻则误伤,重则把自己网站搞挂。解决办法:
- 在 Web 服务里恢复真实 IP(Nginx 用
real_ip模块,Cloudflare 有现成的配置模板,截至撰写时文档很全); - 或者干脆不对 Web 层做 fail2ban,只保护 SSH 和面板这类"直连"的服务。
记住原则:fail2ban 封的 IP 必须是真实客户端 IP,否则宁可不配这个 jail。
fail2ban 和 crowdsec 怎么选
截至撰写时,CrowdSec 是个较新的选择:思路是"众包威胁情报",你的机器把攻击 IP 上报到社区,同时下载社区的黑名单,等于大家一起防。小够的看法:
- 个人 VPS、求稳:fail2ban 足够了,成熟、文档多、资源占用小。
- 多台机器、想省心:可以了解 CrowdSec,一处配置、多台联动。
但别两个同时装着管同一个服务,规则打架比不装还麻烦。选一个,用好。
fail2ban 性能调优
机器多了、jail 多了,fail2ban 本身也占资源。几个调优点:
dbfile用默认的 sqlite 就行,别关——关了每次重启都要重新学,白白多一次扫描。- 日志文件太大时,fail2ban 启动会慢。配合 logrotate 控制单个日志文件大小,别让 auth.log 长到几个 G。
findtime别设太长:findtime 越长,每次要扫描的日志窗口越大。10-30 分钟是甜点区,太长没意义——真有持续攻击,recidive 会接手。
个人 VPS 上,fail2ban 的 CPU 占用基本可以忽略,调优主要是"别给自己找麻烦",不是性能瓶颈。
测试你的 fail2ban 是否真在工作
配完别只看状态,要实测。找另一台机器(或手机热点换 IP),故意输错 3 次 SSH 密码,然后:
# 在服务器上看
sudo fail2ban-client status sshd
应该能看到你的测试 IP 在封禁列表里,Banned IP list 那一行。然后从测试 IP 再连,应该直接超时——证明封禁生效。最后 unbanip 解封,别把自己锁外面做演示。
这个测试建议每次改完 jail 配置都做一次。配了但没生效的 fail2ban,比不配更危险——因为你以为自己有保安,其实保安在睡觉。
fail2ban 自己的日志也要看
/var/log/fail2ban.log 记录了每一次封禁和解封。偶尔翻一翻,能发现:哪个 jail 最忙(说明哪类攻击最多)、有没有误封正常用户、有没有 jail 一直没触发过(可能是 filter 写错了,形同虚设)。一个长期零触发的 jail,99% 是配置有问题——要么日志路径不对,要么正则没匹配上。用前面讲的 fail2ban-regex 重新验证一遍。
多台机器联动
手里有多台 VPS?可以在每台都装 fail2ban,然后用一个中心化的思路:某台机器封掉的 IP,同步到其他机器。简单做法:写个 cron 脚本,定期把各台的封禁 IP 汇总,通过 fail2ban-client set sshd banip 下发。截至撰写时,CrowdSec 把这件事做成了产品(一处上报、多台共享),机器多了可以考虑;机器少的话,脚本够用。
常用运维命令
sudo fail2ban-client status # 看所有 jail 状态
sudo fail2ban-client status sshd # 看 sshd jail 封了谁
sudo fail2ban-client set sshd unbanip 1.2.3.4 # 误封了手动解封
sudo fail2ban-client set sshd banip 5.6.7.8 # 手动拉黑
误封自己是最常见的翻车:出门在外 IP 变了,连输错几次就被自己拦在门外。所以 ignoreip 里务必加上你的固定 IP 和 127.0.0.1:
[DEFAULT]
ignoreip = 127.0.0.1/8 你的家庭IP
小够的总结:fail2ban 是"事后诸葛亮"——它防不住 0day,也防不住一次成功的爆破,它防的是自动化扫描和字典爆破这种"广撒网"的攻击。真正的安全还是靠密钥登录 + 防火墙,fail2ban 是第三道保险。三道都有了,个人 VPS 的 SSH 基本就固若金汤了。
常见问题
Q:fail2ban 和改 SSH 端口,哪个更重要? A:都重要但性质不同。密钥登录是"门锁",改端口是"把门藏起来",fail2ban 是"门口的保安"。优先级:密钥 > 防火墙 > fail2ban > 改端口。别指望任何一个单打独斗。
Q:封禁时间设多长合适? A:SSH 建议 1-24 小时,recidive 给惯犯 7 天。太短没威慑,太长容易误伤自己(比如手机 IP 变动)。ignoreip 白名单一定要配。
Q:fail2ban 会影响正常用户吗? A:正常用户输错 3 次密码以内基本不会触发。真正要小心的是:公司/学校出口 IP 是多人共享的,一个人爆破可能连累整个出口 IP 被封,这种情况用 ignoreip 或调高阈值。
Q:日志轮转后 fail2ban 还工作吗? A:正常工作的。fail2ban 通过 pyinotify 或轮询跟踪日志文件,logrotate 后它会自动跟随新文件,不需要手动干预。
Q:除了 SSH,fail2ban 还能保护什么? A:很多:Nginx/Apache 的 404 扫描、WordPress 登录、邮件服务、甚至自定义应用。思路都一样——找到"失败"的日志特征,写 filter,配 jail。先把 SSH 这一套跑顺,再扩展。