fail2ban如何防御SSH暴力破解
服务器安全巡检别贪多:每天自动检查这十项就够用了
如果你运维过哪怕一台公网服务器,大概率见过这种场景:打开日志一看,满屏的“Failed password for root from 203.0.113.x”。这些尝试一天能刷几千次,甚至几万次。要是手动封,你手速根本跟不上脚本的节奏。Fail2ban 就是专门干这活的——它不是你想象中的“智能防火墙”,而是一个基于日志的模式触发器,本质上是在帮你自动完成本该由人做的事。
原理很简单,但选对模式很重要
Fail2ban 的核心逻辑就三步:读日志 → 匹配失败模式 → 执行封禁。针对 SSH,默认配置通常是监测 /var/log/auth.log(或者 /var/log/secure),寻找“Failed password”这类关键字。一旦某个 IP 在一段时间内失败次数超过阈值,就把这个 IP 加入本地防火墙(iptables/nftables)的黑名单。默认的 [sshd] jail 通常配置 5 次失败后封禁 10 分钟。但说实话,这个默认值在真实场景里太温柔了。一条 500 行/分钟的扫描器日志里,5 次瞬间就满了,10 分钟后 IP 又活蹦乱跳。实际生产中我建议把 maxretry 降到 3,bantime 提到 3600 秒甚至更高,扫描周期时长——但别封死,因为误封自己人时你会后悔。
别只盯着 auth.log 一条路走到黑,试试 conntrack 和 journald
很多人的 fail2ban 配置只盯着 auth.log,但现代系统日志已被 journald 接管。如果你的 SSH 日志走的是 systemd-journald,且没有同步到文件,fail2ban 默认的日志路径根本读不到东西。这种情况下要改用 journald 后端:配置 backend = systemd,匹配 _SYSTEMD_UNIT=sshd.service。更高效的玩法是结合 conntrack:不只看失败的登录失败,还可以监控到某个 IP 在短时间内发起大量 SYN 连接——虽然 fail2ban 原生不直接处理网络流量,但通过自定义 action 配合 nftables,你可以做到“连失败连接计数都能封”。
一个容易被忽略的坑:白名单和递归封禁
我见过最离谱的配置是把 ignoreip 设成空的,结果自己因为输错三次密码被关在门外。白名单里必须加上你自己的办公 IP 或 VPN 网关 IP。另一个坑是“递归封禁”:如果你设的 findtime 太长(比如 48 小时),一个 IP 每天失败几次就会反复进入封禁名单,但真实的攻击者可能早就换源了。建议配合 recidive jail,让重复被触发封禁的 IP 获得更长的惩罚时间——比如第一次封 1 小时,第二次封 1 天,第三次直接封 1 周。这种阶梯式打击比一刀切有效得多。
进阶:用 GeoIP 过滤无国界攻击
Fail2ban 本身不涉及地域判断,但你可以在 action 里调用 ipset 加上 GeoIP 数据库。比如只允许国内 IP 访问 SSH,或者直接封掉哪些从来不访问你服务的国家。配合 fail2ban 的 banaction 自定义脚本,一条命令就能把“刚被 ban 的 IP”自动丢到 GeoIP 黑名单里。这样下一次同 IP 段的攻击连日志都不会刷出来。
最后说一句
Fail2ban 不是银弹。它只能处理基于日志的模式化攻击,遇到分布式慢速暴力破解或 0day 漏洞渗透,它毫无还手之力。但它是在你配置好防火墙、禁用密码登录、启用密钥认证之后的最后一道补充防线。多花十分钟调好 bantime 和 recidive,比写一堆复杂的 iptables 规则更实用——毕竟,运维的终极目标是少熬夜。

参与讨论
默认封10分钟也太短了,我都是直接ban一天
搞过journald的坑,难怪当时fail2ban死活不生效
这个maxretry设3会不会太敏感,我手滑输错一次咋整
真有人把ignoreip设空吗,那不是自己作死😂