给我的小服务器装上 Fail2ban:SSH 防爆破 + 网站防扫描
服务器:阿里云轻量 139.196.31.78(Alibaba Cloud Linux 3 + 1Panel + Docker/openresty)
时间:2026-09-15 凌晨,全程实测通过
一、为什么装
服务器目前没有任何防火墙,22 端口开着密码登录裸奔。虽然日志里暂时只有零星爆破尝试(218.81.98.8 尝试 ubuntu 用户),但公网 22 端口被扫只是时间问题。Fail2ban 的思路很简单:谁犯错,就封谁的 IP——比防火墙白名单更"自动",也更适合我这种懒人运维。
二、装了什么、怎么配的
安装
dnf install -y fail2ban # EPEL 源,1.0.2配置(/etc/fail2ban/jail.local)
EPEL 的包默认把封禁动作指向 firewalld,而这台机器没启用 firewalld,直接用会静默失效——这是第一个必须覆盖的坑。在 jail.local(优先级高于 jail.d/*.conf)里统一改用 iptables-ipset-proto6:用 ipset 承载黑名单,iptables 里只留一条规则,几千个恶意 IP 也不拖慢网络。
两个 jail:
| Jail | 监控 | 触发条件 | 封禁 |
|---|---|---|---|
| sshd | /var/log/secure | 10 分钟内密码错 3 次 | 4h 起,累犯 ×2 递增,最长 2 周 |
| openresty-scan | 5 个站点的 access.log | 10 分钟内命中 5 次恶意路径且返回 403/404 | 1h 起,同样递增 |
自定义 filter(filter.d/openresty-scan.conf)只抓明确的恶意探测特征:.env、.git、.svn、.ssh、.DS_Store、wp-login.php、phpmyadmin、actuator、druid 等。两个刻意的设计:
- 不含
xmlrpc——博客是 Typecho,我平时走 XML-RPC 发文章,万一某次请求失败返回 404 会把自己封了; - 不含宽泛的
admin——Typecho 后台是/admin/,不能误伤。
白名单:回环 + 全部内网网段,永不封禁。封禁记录存 SQLite(/var/lib/fail2ban/fail2ban.sqlite3),服务重启后自动恢复。
踩的最大一个坑:filter 正则"看起来对但永不匹配"
第一版自定义 filter 跑测试样本 8 行命中 0 行,而正则用 Python 单测却能命中。排查了好几轮(还一度怀疑 fail2ban 的方括号转义有问题),最后逐字符二分定位,真相特别朴素:
nginx 日志里协议版本后面紧跟闭合引号,中间没有空格:"GET /.env HTTP/1.1" 404。
我正则里写成了 HTTP/[\d.]+ \"(多了一个空格),所以永不匹配。改成 HTTP/[\d.]+\" 后,8 行测试样本精准命中 5 行恶意、0 行误报。
教训:规则类配置必须用真实样本实测匹配率,"看着对"和"真的对"是两回事。
三、实测验证
fail2ban-client -t语法自检通过- 手动 ban 一个测试 IP →
ipset list里出现、iptables -L INPUT立即插入REJECT ... match-set f2b-sshd src,解封后同步清空 systemctl restart fail2ban→ 封禁记录与防火墙规则全部自动恢复- 上线即抓到真家伙:leakix 的扫描器
46.101.1.225在 01:19 连探/.DS_Store、/.env、/.git/config、/actuator/env、/.vscode/sftp.json共 5 条,全被精准命中——已手动封禁。零误报。
顺带确认了一个关键架构点:1Panel 的 openresty 容器是 host 网络模式,网站流量直接走宿主机 INPUT 链,所以 iptables 封禁对网站同样有效。如果哪天改成 bridge 模式,就需要把 action 挂到 DOCKER-USER 链了。
四、日常使用速查
# 看有哪些 jail 在跑
fail2ban-client status
# 看 SSH / 网站分别封了谁
fail2ban-client status sshd
fail2ban-client status openresty-scan
# 实时拦截日志(最直观)
tail -f /var/log/fail2ban.log
# 内核层确认
iptables -L INPUT -n
ipset list f2b-sshd
ipset list f2b-openresty-scan
# 手动封 / 解封
fail2ban-client set sshd banip 1.2.3.4
fail2ban-client set sshd unbanip 1.2.3.4
fail2ban-client unban --all # 全部解封(慎用)改完配置记得 systemctl restart fail2ban。
五、几句要紧的提醒
- Fail2ban ≠ 防火墙。它只封"犯过事"的 IP,不做端口管控。更根本的防线是在阿里云控制台的安全组里只放行 22/80/443/管理端口。
- 别在 1Panel 里启用自带的防火墙功能,它会清掉 fail2ban 写入的 iptables 规则;真要启用,启用后执行
systemctl restart fail2ban重建。 - 万一哪天把自己 SSH 封了:阿里云控制台 VNC 登录,执行
fail2ban-client unban --all。 - 下一步可以考虑:SSH 改非标端口 + 只留密钥登录关掉密码认证——那是比 fail2ban 更彻底的解法。
没有评论