Featured image of post 建站运维 02:服务器防爆破实战——fail2ban 部署全记录

建站运维 02:服务器防爆破实战——fail2ban 部署全记录

公网服务器 24 小时被爆破 397 次后的反击:fail2ban 安装、Rocky 9 日志 backend 踩坑、封禁链路端到端实测。

环境:腾讯云轻量服务器 / Rocky Linux 9.4 / 2C4G 日期:2026-09-11 背景:服务器 iptables 里有一串 REJECT 名单(云主机安全组件在拦截恶意 IP),查日志发现过去 24 小时有 397 次 SSH 密码爆破尝试——说明我的服务器一直在被人扫。是时候上 fail2ban 了。


一、fail2ban 是什么

一句话:盯着登录日志,谁试错 N 次就把谁关进小黑屋。

工作机制分两半:

  • Filter(侦察兵):实时监控日志(SSH、nginx 等),用正则抓「登录失败」事件,按 IP 计数
  • Action(执法队):某 IP 在 findtime 窗口内失败达到 maxretry 次 → 自动往 iptables 写一条 REJECT 规则,封禁 bantime 时长

整个过程全自动,不需要人盯着。

二、安装(Rocky 9 / dnf 系)

1
2
dnf install -y fail2ban fail2ban-firewalld
fail2ban-client --version   # 装到 v1.1.0

三、配置(/etc/fail2ban/jail.local)

不要改自带的 jail.conf(升级会被覆盖),新建 jail.local:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[DEFAULT]
# 本机 IP 永不封禁(防误伤自己)
ignoreip = 127.0.0.1/8 ::1
bantime  = 24h      # 封多久
findtime = 10m      # 多长的观察窗口
maxretry = 5        # 窗口内失败几次就封
backend  = systemd  # 关键!见下方踩坑
banaction = iptables-multiport

[sshd]
enabled  = true
port     = ssh

[nginx-http-auth]
enabled = true

[nginx-botsearch]
enabled = true

踩坑:Rocky 9 上必须 backend = systemd

传统教程都写监控 /var/log/secure,但 Rocky 9 / RHEL 9 的 SSH 日志默认进 systemd journal,/var/log/secure 是空的或不完整。不改 backend 的话 fail2ban 会显示「No file is currently monitored」——看似在跑,其实在梦游。

启动

1
2
systemctl enable --now fail2ban
systemctl restart fail2ban

四、验证:别只看「启动成功」

服务 active ≠ 在干活。要验证三件事:

1. 日志源有没有盯上

1
fail2ban-client status sshd

关键看输出里的 Journal matches:

1
Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd + _COMM=sshd-session

有这行 = 侦察兵真的在盯 sshd 的 journal。如果显示 No file is currently monitored,就是上面的 backend 坑。

2. 封禁链路端到端实测(重要!)

光看 status 不够,手动封一个测试 IP 验证整条链路:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 203.0.113.99 是 TEST-NET-3 保留地址,随便用不会误伤真人
fail2ban-client set sshd banip 203.0.113.99

# 看 fail2ban 认账了
fail2ban-client status sshd
# Currently banned: 1 / Banned IP list: 203.0.113.99

# 关键:确认 iptables 里真的出现了拦截规则
iptables -L -n | grep -A2 f2b-sshd
# Chain f2b-sshd (1 references)
# REJECT  0  --  203.0.113.99  0.0.0.0/0  reject-with icmp-port-unreachable

# 测完放出来
fail2ban-client set sshd unbanip 203.0.113.99

只有 iptables 里亲眼看到 REJECT 规则,才算部署完成。

3. status 输出字段怎么看

1
2
3
4
5
6
7
8
9
Status for the jail: sshd
├─ Filter
│  ├─ Currently failed: 0     ← 当前观察窗内正在试错的 IP 数
│  ├─ Total failed: 0         ← 启动以来抓到的失败总数(不追溯启动前的)
│  └─ Journal matches: ...    ← 盯的日志源
└─ Actions
   ├─ Currently banned: 0     ← 此刻小黑屋里关着几个
   ├─ Total banned: 1         ← 历史累计(含手动测试那个)
   └─ Banned IP list: ...     ← 当前名单

五、日常运维

1
2
3
4
fail2ban-client status           # 看有几个 jail 在跑
fail2ban-client status sshd      # 看战果(封了几个、是谁)
fail2ban-client set sshd unbanip <IP>   # 误封了手动放人
tail -f /var/log/fail2ban.log    # 看实时动态

六、后续加固路线

fail2ban 只是第一道防线,后面还排着:

  1. SSH 密钥登录 + 关密码登录——做完这个,爆破直接归零(釜底抽薪)
  2. 安全组收敛——22 端口只对常用 IP 段开放
  3. dnf-automatic 自动安全更新
  4. 登录成功告警——有人登上服务器立刻通知我

七、总结

  • 部署成本:10 分钟
  • 维护成本:零(全自动)
  • 收益:397 次/天的爆破尝试,从「全靠密码强度硬扛」变成「试错 5 次关 24 小时」

公网服务器第一课:你以为是安静的小站,扫描器眼里是嗷嗷待宰的肉鸡。fail2ban 该装就早点装。

使用 Hugo 构建
主题 Stack 由 Jimmy 设计