Fail2Ban 是一套用 Python 编写的入侵防御工具,核心逻辑是监控指定日志文件,当某个来源 IP 在设定时间内匹配到足够多的失败记录时,就调用系统防火墙或云安全组接口将其临时拉黑。对云服务器用户来说,公网 IP 每天都会被大量扫描,如果不做防护,SSH 密码被撞破只是时间问题。Fail2Ban 不依赖复杂规则,往往只需复制几个配置块就能上线。

先确认服务器是否已经存在大量暴力破解尝试。以 Ubuntu 为例,执行 grep 'Failed password' /var/log/auth.log | tail 就能看到最近失败记录。如果输出中反复出现同一 IP,说明有机器在撞库。此时部署 Fail2Ban 后,这些来源会被自动拦截,日志噪音也会明显下降。
Fail2Ban 的安装与基础环境准备
Fail2Ban 基本覆盖所有主流 Linux 发行版,安装过程并不复杂。Ubuntu 或 Debian 系统执行 apt update && apt install fail2ban -y 即可;CentOS、RHEL、AlmaLinux 等需要先引入 EPEL 仓库,再执行 yum install epel-release -y && yum install fail2ban -y。安装完成后,使用 systemctl enable fail2ban --now 让服务开机自启并立即运行。
部署前还要确认系统防火墙状态。Fail2Ban 默认通过 iptables 或 firewalld 来插入封禁规则,如果系统里这两个组件都没有启用,封禁动作可能不会真正生效。云服务器通常还会有一层安全组,Fail2Ban 在本机防火墙添加的规则只影响实例内部流量,不会修改云厂商控制台的安全组策略。因此需要保证安全组允许正常管理端口,同时不要把 Fail2Ban 的封禁动作误认为安全组已经自动更新。
另一个容易被忽略的点是日志服务。Fail2Ban 依赖 rsyslog 或 systemd journal 提供的登录失败日志。如果日志服务被关闭或者被重定向到非常规路径,Fail2Ban 可能监控不到任何失败记录。检查 systemctl status rsyslog 或 systemctl status systemd-journald,确保日志正常生成后再继续配置。
核心配置 jail.local 与参数解析
默认配置文件位于 /etc/fail2ban/jail.conf,官方不建议直接修改这个文件,因为包升级时它可能被覆盖。正确的做法是把它复制成 jail.local:执行 cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local。Fail2Ban 会优先读取 local 后缀的文件,这样既保留了升级后的新配置,又能用自己的修改覆盖默认值。
打开 jail.local 后,先找到 [DEFAULT] 部分。这里定义全局参数,所有 jail 默认继承。常用选项如下表所示。
| 参数 | 作用 | 常见设置 |
|---|---|---|
| ignoreip | 永不封禁的 IP 或网段,多个用空格分隔 | 127.0.0.1/8 办公室出口IP |
| bantime | 封禁时长,单位秒,负数表示永久封禁 | 3600 或 86400 |
| findtime | 统计失败次数的时间窗口 | 600 |
| maxretry | 窗口内允许的最大失败次数 | 5 |
| destemail | 告警邮件收件地址 | admin@ipipp.com |
| action | 触发后执行的动作,如防火墙规则 | iptables-multiport 或 cloudflare |
云服务器上一定要把 ignoreip 设置成自己的固定办公 IP 或家庭出口 IP,避免误封后无法登录。如果使用跳板机或 VPN,也要把对应网段写进去。多个地址用空格分隔,比如 ignoreip = 127.0.0.1/8 203.0.113.10。
bantime 不建议设置得太短。很多扫描器会持续不断尝试,封 10 分钟几乎没有意义,通常 1 小时起步。如果正在遭受集中攻击,可以临时调成 86400 秒甚至 -1 永久封禁。但永久封禁要谨慎使用,因为攻击者可能使用动态 IP,以后被正常用户复用反而会误伤。
启用 SSH 防护并适配不同发行版
默认的 jail.conf 里已经包含 [sshd] 配置,但它的 enabled 默认是 false。最简单的方式是直接在 jail.local 末尾追加一段:
[sshd]enabled = trueport = sshlogpath = /var/log/auth.logmaxretry = 5bantime = 3600findtime = 600
这里最容易出错的就是 logpath。不同发行版的 SSH 登录日志路径并不一样:Ubuntu、Debian 一般是 /var/log/auth.log,而 CentOS、RHEL、AlmaLinux 通常是 /var/log/secure。如果照搬教程里的路径,服务能启动但永远抓不到失败记录。不确定时可以用 ls /var/log/auth.log /var/log/secure 查看哪个文件存在。
修改完成后执行 systemctl restart fail2ban,再用 fail2ban-client status 检查。如果看到 Jail list: sshd,说明 SSH 防护已经加载。此时从另一台机器故意输错几次 SSH 密码,就会触发封禁。注意在测试时不要使用被加入 ignoreip 的地址,否则永远不会被封。
自定义过滤规则与告警通知
Fail2Ban 把日志匹配规则称为过滤条件,定义在 /etc/fail2ban/filter.d/ 目录下。SSH 的默认过滤规则通常能覆盖常见失败类型,但如果需要防护 Web 登录表单、FTP 或数据库服务,就需要额外创建过滤器。过滤器使用正则表达式匹配日志中的失败记录,并从记录中提取来源 IP。
在自定义过滤规则前,可以先用 fail2ban-regex 命令测试。例如拿到几行真实日志后执行 fail2ban-regex /var/log/syslog 'Failed password for .* from <HOST>',观察输出中 Matched 数量是否大于 0。这样可以避免配置上线后才发现正则根本不匹配。
告警通知建议开启。把 [DEFAULT] 里的 destemail 设为管理员邮箱,并确认 action 包含发送邮件的动作,如 action = %(action_mwl)s。这样每当 IP 被封禁,Fail2Ban 会发送包含日志片段和 whois 信息的邮件。邮件告警能让你及时感知正在发生的攻击,而不必每天翻看日志。
验证封禁效果与日常管理
配置完成后,验证是否真的封禁成功。先查看某个 jail 的统计信息:fail2ban-client status sshd,它会列出当前封禁的 IP 列表。再查看系统防火墙规则,如果使用 iptables,执行 iptables -L -n 能看到 fail2ban-sshd 链中多出的 IP;如果使用 firewalld,可以用 firewall-cmd --direct --get-all-rules 查看。
确认封禁生效后,如果需要临时解封某个 IP,比如同事误输密码过多被锁,可以用 fail2ban-client set sshd unbanip 203.0.113.10。如果误封 IP 很频繁,建议把对应的出口地址加进 ignoreip,或适当调高 maxretry 值。
日常维护中,重启 Fail2Ban 后服务会从数据库恢复仍在封禁期内的 IP,但如果不使用默认的数据库持久化,部分发行版可能只保留本次运行期间的数据。因此对于长期运行的云服务器,建议保留默认数据库配置,并定期检查 /var/log/fail2ban.log 中的封禁和解封记录。
常见问题与云服务器注意事项
很多人配置完发现 Fail2Ban 状态正常,但暴力破解没有任何减少。这种情况先检查日志路径是否写对,其次确认 maxretry 是否过大导致攻击者还没触发封禁就换 IP 了。把 maxretry 设为 3 到 5,findtime 设为 300 到 600 秒,能更灵敏地拦住短时高频扫描。
云服务器与物理机的一个区别是外部还有安全组或防火墙。Fail2Ban 在本机丢掉的流量,外部安全组可能早已放行,但这并不影响封禁效果,因为攻击包到达实例后会被本机防火墙丢弃。反过来,如果安全组完全关闭了 SSH 端口,Fail2Ban 就监控不到内部登录失败,也就不会触发封禁。因此要合理设置安全组,保留必要的登录端口,同时依靠 Fail2Ban 做动态拦截。
如果服务器上运行了 Docker 或其他容器服务,Fail2Ban 默认读取宿主机日志,可能无法直接看到容器内部的登录失败记录。这种情况下需要把容器日志挂载到宿主机,或者让容器把认证日志写入指定文件,再用 Fail2Ban 监控该路径。否则即使配置了容器服务的防护规则,也无法正确提取来源 IP。
最后提醒,Fail2Ban 不是万能的,它无法阻止使用大量不同 IP 的分布式暴力破解。对于这种攻击,还需要配合密钥登录、禁用密码登录、修改 SSH 端口、使用云厂商的 DDoS 防护或 WAF 等手段。但作为第一道自动化防线,Fail2Ban 能显著降低绝大多数扫描器和撞库脚本的成功概率,是云服务器安全基线的必要组成部分。

