Fail2Ban封禁失效主因是日志未被正确识别,需依次排查日志路径与后端配置匹配、failregex是否命中、计数逻辑(findtime/maxretry)是否生效、封禁动作是否真实写入防火墙。

Fail2Ban 封禁失效,八成不是防火墙没起作用,而是日志根本没被正确识别——匹配失败,后续所有动作都成空谈。排查核心要聚焦在“日志是否被读到、是否被正则捕获、是否被计数”这三步上。
确认日志路径与后端配置是否匹配
Fail2Ban 必须准确读取目标日志文件,否则连第一行都看不到。常见错配包括:
- CentOS/RHEL 默认用 /var/log/secure,Ubuntu/Debian 默认用 /var/log/auth.log;若 jail 中 logpath 指向错误路径,filter 就永远无事可做
- 后端(backend)类型影响实时性:systemd 后端需确保 journalctl 可读且单位名正确(如
sshd.service),auto 或 polling 后端则依赖文件轮询间隔,可能延迟数秒 - 权限问题:fail2ban 进程用户(通常是 root)必须有读取日志文件的权限;SELinux 启用时,还需检查
audit2why是否报出 avc denied
验证 failregex 是否真正命中日志行
这是最常卡住的环节。Fail2Ban 的正则不支持 PCRE 全特性,且对空格、转义、时间戳位置极其敏感。实操建议:
- 用
fail2ban-regex /var/log/secure /etc/fail2ban/filter.d/sshd.conf手动测试,注意输出中的 Lines read(是否真读到了)、Matched(是否成功匹配)、Failed(是否误判合法日志) - 确保
<host></host>宏出现在正则中且位置合理;它会自动匹配 IPv4/IPv6,但不能写成[0-9.]+这类手写 IP 正则,否则提取失败导致计数为空 - 如果日志含虚拟主机字段(如 Apache 的
vhost)、前置时间格式不统一,需调整正则开头,避免因字段偏移而整行失配
检查计数逻辑与时间窗口是否符合预期
即使正则匹配成功,IP 也不一定被封——它还要通过 findtime/maxretry 的双重校验:
- findtime 是滑动窗口(单位秒),不是固定周期;例如设为 600 秒,表示“最近 10 分钟内累计失败次数”,而非“每 10 分钟清零重算”
-
maxretry 是该窗口内的总触发次数;若日志里某 IP 每 15 秒试一次,10 分钟内达 40 次,但 maxretry=3,那它早该被封了——此时应查是否被
ignoreip白名单排除,或是否被ignoreregex过滤掉 - 用
fail2ban-client status sshd查看 Currently failed 和 Total failed,两者差异大说明匹配不稳定;若 Currently banned 为 0 但 Total banned 有值,说明封禁已过期或未生效
确认封禁动作是否实际执行
匹配和计数都正常,但 IP 仍能访问?重点检查动作链是否落地:
- 运行
iptables -L -n | grep <em>IP</em>或nft list chain inet fail2ban sshd,确认规则真实存在于防火墙中 - firewalld 用户需确认 action 设为
firewallcmd-ipset而非旧版iptables-multiport,否则规则会被 firewalld 自动清理 - 检查
bantime单位:数值默认是秒,写成bantime = 1h会解析失败,应为bantime = 3600或bantime = 1h(仅在较新版本支持,需确认文档)

















