CentOS 7 上 fail2ban 防护 SSH:从「jail 不加载」到「递增封禁」完整复盘

环境:CentOS 7 + fail2ban 0.11.2(EPEL)+ SSH 改到 57022 端口 + systemd 日志

现象:fail2ban-client status 只看到 3x-ipl,status sshd 报 Sorry but the jail 'sshd' does not exist

一、事故现场

按常规写法把配置塞进 /etc/fail2ban/jail.local:

 [DEFAULT]
# 初始封禁时长
bantime          = 1h

# 启用递增封禁 
bantime.increment = true
bantime.factor    = 2
bantime.maxtime   = 1w

# 统计窗口
findtime         = 10m

# 默认失败次数
maxretry         = 1

# systemd
backend          = systemd

# 白名单
ignoreip         = 127.0.0.1/8 ::1

[sshd]
enabled  = true
port     = 57022
maxretry = 1

然后:

systemctl enable --now fail2ban
fail2ban-client restart sshd
# ERROR NOK: ('sshd',) Sorry but the jail 'sshd' does not exist
fail2ban-client status
# Jail list: 3x-ipl

服务起来了,但 sshd jail 根本没被加载。

二、根因

CentOS 7 的 fail2ban 0.11.x 有个坑:

  • jail.conf 里 [sshd] 默认 enabled = false
  • 某些发行版打包下,写在 jail.local 的 [sshd] 段不一定被合并进最终 jail 列表
  • 同时你 backend=systemd 又写了 logpath=/var/log/secure(上一版遗留),两者互斥,更容易让 jail 启动失败被跳过

结果就是:fail2ban 只加载了自带启用的 3x-ipl,sshd 被静默丢弃。

三、正确写法(两处关键修改)

1)jail.local 只放 DEFAULT,不放 [sshd]

[DEFAULT]
bantime           = 1h
bantime.increment = true
bantime.factor    = 2
bantime.maxtime   = 1w
findtime          = 10m
maxretry          = 3
backend           = systemd
ignoreip          = 127.0.0.1/8 ::1 你的管理IP

2)单独建 /etc/fail2ban/jail.d/sshd.local

[sshd]
enabled  = true
port     = 57022
backend  = systemd
maxretry = 1

关键点:

  • backend=systemd 时不要写 logpath,journal 匹配由 filter 的 journalmatch 决定
  • 用 jail.d/*.local 覆盖,比挤在 jail.local 里稳

3)重载

fail2ban-client -t          # 先语法校验
systemctl restart fail2ban
fail2ban-client status
# 应看到 Jail list: sshd
fail2ban-client status sshd

四、顺手把「越屡教不改封越久」讲清楚

递增封禁三个参数必须同时出现,否则 bantime=1h 永远 1 小时:

bantime.increment = true
bantime.factor    = 2
bantime.maxtime   = 1w

效果(同 IP 反复触发):

第 N 次被封实际封禁
11h
22h
34h
…上限 1w

⚠️ maxretry=1 能用但极容易误伤自己(手抖一次就封),生产建议 maxretry=2 起步,自己 IP 一定进 ignoreip。

五、验证链路(别只看 systemctl active)

# 1 配置语法
fail2ban-client -t

# 2 jail 真加载没
fail2ban-client status | grep sshd

# 3 backend 是不是 systemd
fail2ban-client get sshd backend

# 4 journal 里有没有 sshd 失败日志(数据源)
journalctl -u sshd -f | grep -i failed

# 5 实时看封禁动作
journalctl -u fail2ban -f

# 6 手动解封自己
fail2ban-client set sshd unbanip x.x.x.x

如果 journalctl -u sshd 是空,先确认服务名:

systemctl status sshd || systemctl status ssh

unit 叫 ssh 的话,在 sshd.local 里补:

journalmatch = _SYSTEMD_UNIT=ssh.service

六、CentOS 7 额外坑:SELinux

老 CentOS 7 上 fail2ban 读 journal / 调 firewall-cmd 可能被 SELinux 拦,表现为 jail 起来但永远 0 命中:

grep fail2ban-server /var/log/audit/audit.log | audit2allow -M mypol
semodule -i mypol.pp
systemctl restart fail2ban

七、最终可直接抄的落地版

mkdir -p /etc/fail2ban/jail.d

cat > /etc/fail2ban/jail.local <<'EOF'
[DEFAULT]
bantime           = 1h
bantime.increment = true
bantime.factor    = 2
bantime.maxtime   = 1w
findtime          = 10m
maxretry          = 3
backend           = systemd
ignoreip          = 127.0.0.1/8 ::1 你的运维IP
EOF

  
cat > /etc/fail2ban/jail.d/sshd.local <<'EOF'
[sshd]
enabled  = true
port     = 57022
backend  = systemd
maxretry = 1
EOF

八、总结

  • jail 'sshd' does not exist ≠ 配置写错语法,而是 jail 没进加载列表
  • CentOS 7 + fail2ban 0.11:[sshd] 放 jail.d/sshd.local 比塞 jail.local 稳
  • systemd backend 和 logpath 二选一,别混用
  • 递增封禁缺 increment/factor/maxtime 就是假递增
  • 自己 IP 不进 ignoreip,迟早把自己关门外

发表评论