Fail2ban通过正则匹配auth.log或secure中的失败登录行(如“Failed password”)识别SSH暴力破解,需确保日志路径、格式、防火墙后端(iptables/nftables/ufw)及时间戳时区配置正确。
Fail2ban 怎么识别 SSH 暴力破解日志
fail2ban 不是靠猜,它靠的是正则匹配 auth.log(或 secure)里的失败登录行。默认规则里 sshd jail 会监听 failed password 或 invalid user 这类关键词,但前提是日志格式对得上。
常见错误现象:fail2ban-client status sshd 显示 0 个被封 IP,但明明刚被扫了几十次——大概率是日志路径不对,或系统用的 journald 而没配 systemd-journal 后端。
- 确认日志路径:Debian/Ubuntu 默认是
/var/log/auth.log,CentOS/RHEL 是/var/log/secure,必须和filter.d/sshd.conf里的logpath一致 - 如果用了
rsyslog转发或自定义日志格式,要同步更新failregex,比如匹配Connection closed by invalid user就得加进正则 - 用
fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf手动测试匹配效果,别等真被扫了才验证
封禁后怎么让 iptables 规则真正生效
Fail2ban 默认用 iptables 动作封 IP,但很多新装系统默认用 nftables,或者开了 ufw,这时候 iptables -L 看不到封禁规则,是因为 Fail2ban 写的是旧链,而实际流量走的是新链或 ufw 的 wrapper。
使用场景:你改了 action = %(action_)s,重启服务,fail2ban-client status sshd 显示有封禁,但 IP 还能连上 SSH。
- 检查当前防火墙后端:运行
sudo systemctl status nftables或sudo ufw status verbose,若活跃,就得换 action - 推荐做法:在
jail.local里指定banaction = nftables(需 Fail2ban ≥ 0.11)或banaction = ufw(需提前ufw allow OpenSSH) - 避免混用:别让 Fail2ban 和手动
iptables -I INPUT共存,规则顺序错乱会导致放行失效
为什么日志里没失败记录,但 Fail2ban 还是误封
不是所有“失败登录”都会写进 auth 日志。比如 SSH 配置了 PermitRootLogin no,攻击者直连 root,OpenSSH 可能只记 User root from ... not allowed,而默认 sshd.conf 的 failregex 没覆盖这行,导致 Fail2ban 漏判;反过来,某些合法客户端(如老旧脚本、特定终端)触发非标错误,又被正则误捕,就造成误封。
参数差异:Fail2ban 的 maxretry、findtime、bantime 共同决定敏感度。设成 maxretry = 3、findtime = 600,等于“10 分钟内输错 3 次就拉黑”,对共享办公环境太激进。
- 调低敏感度:生产环境建议
maxretry = 5、findtime = 3600(1 小时),避开临时网络抖动或用户手滑 - 排除白名单:在
jail.local加ignoreip = 192.168.1.0/24 10.0.0.5,内网开发机不参与封禁逻辑 - 查误封证据:用
sudo fail2ban-client get sshd banned查当前黑名单,再翻journalctl -u fail2ban -n 50看触发原因
访问日志监控要不要替代 Fail2ban
单纯用 awk + tail -f 实时扫 access.log 做限流,看起来轻量,但没法和系统级防火墙联动,只能返回 429 或重定向,攻击者换个 User-Agent 或代理就能绕过。Fail2ban 的价值不在“分析日志”,而在“把分析结果变成内核层的丢包动作”。
性能影响很小:Fail2ban 默认每秒最多读一次日志(usedns = no 关闭反解),单核 CPU 上撑几千 IP 封禁毫无压力;真正卡住的是日志轮转没配好,比如 logrotate 没发 SIGHUP 给 rsyslog,导致 Fail2ban 一直 hold 着旧文件句柄,磁盘越攒越多。
- Web 应用层暴力破解(如 WordPress 登录页)该用 Fail2ban,但要配
nginx或apache-authfilter,别硬套sshd - 不要在
access.log里依赖401状态码判断爆破——有些 CMS 把登录失败全打成200,得结合 POST body 或 URI 路径(如/wp-login.php)来写 regex - 日志路径权限必须是
644或 Fail2ban 用户可读,否则fail2ban-server启动时静默失败,systemctl status fail2ban里看不到报错
最常被忽略的是日志时间戳时区——如果服务器用 UTC,但 Fail2ban 配了 datepattern = %%Y-%%m-%%d %%H:%%M:%%S 却没声明 logtimezone = UTC,时间窗口计算就会偏移,封禁可能延后几分钟甚至失效。


















