教程 · 安全加固
用 fail2ban 拦截 SSH 暴力破解
难度
进阶
预计时长
20 分钟
步骤
6 步
最近修订
基准系统
Debian 12
要点
用 fail2ban 拦截 SSH 暴力破解
fail2ban 读取认证日志,对反复失败的来源 IP 自动下发防火墙封禁。在 Debian 12 上安装后要新建 /etc/fail2ban/jail.local,把 sshd 段落的 backend 设为 systemd(bookworm 默认不装 rsyslog,没有 /var/log/auth.log),并把 port 改成实际使用的 SSH 端口,否则封禁规则会挂在 22 上,形同虚设。
前置条件
开始之前,先确认这些都具备
- 已完成 SSH 加固(密钥登录)
- sudo 权限
- 已启用 ufw 或 nftables
操作步骤
共 6 步
步骤 01 / 06
安装 #
fail2ban 在官方仓库里,不需要第三方源。装完先别急着改配置,看一眼服务状态即可。
Shell sudo apt update && sudo apt install -y fail2ban systemctl status fail2ban --no-pager步骤 02 / 06
写 jail.local,不要动 jail.conf #
jail.conf 会在软件包升级时被覆盖,所有自定义都写进 jail.local。这里有两个关键项:backend = systemd 让 fail2ban 读 journald,而不是去找并不存在的 /var/log/auth.log;port 必须写实际的 SSH 端口。另外 banaction 建议与你的防火墙保持一致。
配置文件 # /etc/fail2ban/jail.local [DEFAULT] # 把自己的固定 IP 放进白名单,避免误封 ignoreip = 127.0.0.1/8 ::1 203.0.113.0/24 bantime = 1h findtime = 10m maxretry = 5 # 用 ufw 时改成 ufw,避免两套规则打架 banaction = ufw [sshd] enabled = true backend = systemd port = 22022 maxretry = 4 bantime = 24h步骤 03 / 06
校验配置并启动 #
fail2ban-client -d 会把最终生效的配置全部打印出来,写错的段落在这里就会暴露。确认无误再重启服务。
Shell sudo fail2ban-client -d > /dev/null && echo "配置可解析" sudo systemctl enable --now fail2ban sudo systemctl restart fail2ban sudo fail2ban-client status步骤 04 / 06
确认 sshd jail 真的在工作 #
「服务在 running」和「jail 在数」是两回事。看 sshd jail 的状态:如果 Currently failed 与 Total banned 始终是 0,而 journald 里明明有失败记录,就说明 backend 配错了。
Shell sudo fail2ban-client status sshd # 对照一下日志里真实的失败次数 sudo journalctl -u ssh --since "1 hour ago" | grep -c "Failed password"步骤 05 / 06
解封与手动封禁 #
误封自己是迟早的事,记住解封命令比记住封禁命令更重要。真被封了又没有别的入口,就从控制台 VNC 进去执行。
Shell sudo fail2ban-client set sshd unbanip 203.0.113.55 sudo fail2ban-client set sshd banip 198.51.100.7 # 查看当前所有封禁 sudo fail2ban-client banned步骤 06 / 06
(可选)给 Nginx 加一个 jail #
同一套机制可以用在 Web 上:nginx-http-auth 拦 HTTP 基本认证爆破,nginx-botsearch 拦满地找后门文件的扫描器。别一次全开,先跑一周观察误报率。
配置文件 # 追加到 /etc/fail2ban/jail.local [nginx-http-auth] enabled = true logpath = /var/log/nginx/error.log [nginx-botsearch] enabled = true logpath = /var/log/nginx/access.log maxretry = 10
常见错误
这一步最容易踩的坑
下面每一条都对应一个真实会发生的故障。先读完再动手,比出问题之后再回来查要省时间。
- Debian 12 默认不装 rsyslog,没有 /var/log/auth.log。不设 backend = systemd 的话,sshd jail 会静默地什么都不做 —— 服务状态还是绿的,这一点最容易骗人。
- port 忘了改成自定义端口。封禁规则挂在 22 上,而攻击者敲的是 22022,等于没封。
- ignoreip 里没写自己的 IP,手滑几次密码就把自己关在门外了。
- 同时用 ufw 又让 fail2ban 走默认的 iptables 动作。两套规则不冲突但会互相掩盖,排查时非常费神,统一成 banaction = ufw。
- 把 bantime 设成永久。IP 池会轮换,永久封禁只会让规则表无限膨胀,还可能误伤后来使用同一个动态 IP 的正常用户。
- fail2ban 不能替代密钥登录。关掉密码认证之后,爆破从「有可能成功」变成「不可能成功」,此时 fail2ban 的价值主要是省日志和省 CPU。
这篇教程的边界
- 命令以 Debian 12 为准。Ubuntu 与 Rocky Linux 的差异只在正文明确标注之处,未标注的部分请以你所用发行版的官方文档为准。
- 示例中的 IP 来自文档保留段 203.0.113.0/24,域名为 example.com,端口为示意值。复制后必须替换成自己的值, 原样执行不会有任何效果。
- 教程不能替代备份。任何会改动数据或线上流量的步骤,执行前先确认有一份验证过能恢复的备份。
- 本站不提供任何用于绕过网络审查的配置或说明,这篇也不例外。
发现命令过时或有误,请发邮件到 [email protected]。 指出错误的邮件比沉默的旧文档有价值得多。