fail2ban未封禁sshd的根本原因是日志路径或正则不匹配:需确认logpath与实际日志路径(/var/log/auth.log或/secure)一致,用fail2ban-regex测试匹配;rhel 8+需配置syslogfacility authpriv;后端需与系统防火墙一致(iptables/nftables);openssh 8.9+日志格式变更要求更新filter的failregex。

fail2ban 为什么连 sshd 都没封?
常见现象是配置完 fail2ban,journalctl -u fail2ban 显示服务正常,但暴力扫 ssh 的 IP 就是不进 iptables 或 nftables 规则。根本原因通常是日志路径或正则没对上。
-
sshd日志默认在/var/log/auth.log(Debian/Ubuntu)或/var/log/secure(RHEL/CentOS),fail2ban的[sshd]节里logpath必须精确匹配,不能写错路径或漏掉通配符 - 用
fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf手动测试匹配效果,看有没有Matched行;没匹配上就说明 filter 规则压根没抓到失败登录行 - RHEL 8+ 默认用
journald,sshd日志可能不落盘,得在/etc/ssh/sshd_config加SyslogFacility AUTHPRIV并重启sshd,否则fail2ban读不到原始日志
用 iptables 还是 nftables?
fail2ban 0.11+ 默认走 nftables,但很多生产环境还是老系统跑 iptables,混用会导致规则不生效甚至冲突。
- 查当前后端:
fail2ban-client get sshd banaction,输出是iptables-multiport还是nftables-multiport - 强制指定后端:在
/etc/fail2ban/jail.local的[sshd]下加banaction = iptables-multiport,同时确保系统没装nftables或已禁用其 service - 注意
iptables的INPUT链顺序——如果已有ACCEPT规则在前,fail2ban插入的DROP就会被跳过;用iptables -L INPUT -n --line-numbers确认位置
sshd 登录失败日志格式变了怎么办?
OpenSSH 8.9+ 默认禁用了密码认证(PasswordAuthentication no),且日志中失败提示从 Failed password 变成 userauth_pubkey 或 invalid user,老版 sshd.conf filter 就会失效。
- 检查实际日志内容:
grep "Invalid user\|Failed password\|userauth_pubkey" /var/log/auth.log | tail -5 - 升级 filter:用
fail2ban-client get sshd ignoreself看是否误判本机 IP;把/etc/fail2ban/filter.d/sshd.conf替换为新版(或从 GitHub 拉官方最新版),重点看failregex是否覆盖invalid user和Connection closed by authenticating user - 避免过度封禁:加
ignoreregex = ^.*sshd.*@.*port.*$过滤扫描器伪造的源端口日志,防止误伤合法客户端
封禁后 SSH 连不上,怎么快速解封?
手抖把自己封了、或者开发同事被误杀,最急的是立刻恢复访问,而不是查日志。
- 临时清空所有
fail2ban封禁:fail2ban-client unban --all(注意不是stop,停服务会丢状态) - 只解某个 IP:
fail2ban-client set sshd unbanip 192.168.1.100 - 如果
fail2ban没响应,直接删防火墙规则:iptables -D INPUT -s 192.168.1.100 -j REJECT(iptables)或nft delete element inet fail2ban sshd { 192.168.1.100 }(nftables) - 别依赖
bantime自动解封——默认 10 分钟太长,调试期建议设成bantime = 60,确认稳定后再调高
真正麻烦的是多层防护叠加:比如云厂商安全组 + 主机 iptables + fail2ban,封一个 IP 得查三层,漏掉一层就以为“没封成功”。动手前先 curl ifconfig.me 确认当前出口 IP,再决定该去哪层解封。










