环境: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 次被封 | 实际封禁 |
|---|---|
| 1 | 1h |
| 2 | 2h |
| 3 | 4h |
| … | 上限 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稳 systemdbackend 和logpath二选一,别混用- 递增封禁缺
increment/factor/maxtime就是假递增 - 自己 IP 不进
ignoreip,迟早把自己关门外