跳到主要内容
注册无需实名认证
安云主机 AnYun VPS

教程 · 安全加固

用 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

  1. 步骤 01 / 06

    安装 #

    fail2ban 在官方仓库里,不需要第三方源。装完先别急着改配置,看一眼服务状态即可。

    Shell
    sudo apt update && sudo apt install -y fail2ban
    systemctl status fail2ban --no-pager
  2. 步骤 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
  3. 步骤 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
  4. 步骤 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"
  5. 步骤 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
  6. 步骤 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]。 指出错误的邮件比沉默的旧文档有价值得多。

联系 工单
扫码
手机访问

扫码在手机上打开