跳转到内容

Fail2ban 防暴力破解配置完全指南 | SSH 安全防护教程

Fail2ban Security Protection

如果你使用的是默认端口(22)和传统的密码登录方式来连接你的 VPS,过不了几天你去查看系统日志,一定会发现大量的“失败登录尝试”。这是因为互联网上随时有无数的扫描脚本和僵尸网络在无差别地尝试爆破所有服务器的 SSH 密码。

这不仅占用系统资源,万一密码设得比较简单,服务器直接就沦陷成了“肉鸡”。

为了解决这个问题,除了 改用 SSH 密钥登录 之外,安装一款能自动识别“多次密码输入错误”并将其 IP 封禁的防火墙工具是非常有必要的。Fail2ban 就是其中的黄金标准。

什么是 Fail2ban?

Fail2ban 是一款强大的防御软件。它的工作原理很简单: 后台默默扫描系统日志(如 /var/log/auth.log),如果它发现某个 IP 地址在短时间内连续多次尝试密码失败,它就会自动去修改防火墙(iptables/ufw/firewalld 等)规则,把这个来源 IP 给拉黑(封禁)一段时间。

一次配置,终身免疫。

Fail2ban vs 其他安全工具对比

特性Fail2banDenyHostsiptables 手动规则云服务商 WAF
自动化程度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
灵活性⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
支持协议多种(SSH, Web, Mail等)仅 SSH所有取决于服务
配置难度中等简单困难简单
资源占用极低
免费开源

步骤一:安装 Fail2ban

Fail2ban 在包括 Debian 和 Ubuntu 在内的绝大部分 Linux 发行版的官方软件源里都能直接找到。

Debian/Ubuntu 安装

  1. 首先更新一下软件包列表:
    bash
    apt update
  2. 执行安装命令:
    bash
    apt install fail2ban -y

CentOS/RHEL 安装

bash
# 启用 EPEL 仓库
yum install epel-release -y

# 安装 Fail2ban
yum install fail2ban -y

验证安装

bash
# 检查版本
fail2ban-client --version

# 检查服务状态
systemctl status fail2ban

安装完成后,Fail2ban 这个服务会自动启动并在后台默默运行。


步骤二:新建 Fail2ban 自定义配置(核心动作)

Fail2ban 所有的默认“封禁规则”和“监狱(Jail)”配置都存放在 /etc/fail2ban/jail.conf 这个文件里。 但是,官方强烈建议:不要去修改原始的 jail.conf 文件! 因为一旦未来软件升级,你的修改就有丢失的可能。

正确的做法是:新建一个 jail.local 文件,把属于我们自己的改动写在里面。 它的优先级比原始文件高。

基础配置

  1. 使用你最爱的编辑器打开(新建)这个文件:

    bash
    nano /etc/fail2ban/jail.local
  2. 将以下最基础、最实用的防护规则配置项 复制并粘贴 进去:

    ini
    [DEFAULT]
    # 这是默认设置
    # 忽略你自己的本地 IP 不受封禁(相当于白名单),如果你有固定 IP,也可以加在这里,用空格隔开。
    ignoreip = 127.0.0.1/8 ::1
    
    # 封禁时间:被拉黑后,多长秒数放出来。这里填 86400 (秒) 相当于封禁一天。
    bantime  = 86400
    
    # 找茬时间窗口:在这个时间跨度内计算失败次数。这里设为 600 秒(十分钟)。
    findtime = 600
    
    # 最大容忍次数:10 分钟内,一旦失败次数大于等于 3 次,立刻封禁。
    maxretry = 3
    
    
    [sshd]
    # 开启针对 SSH 的监控监狱
    enabled = true
    
    # 如果你改过 SSH 服务用的端口,请在这里写上你的新端口,如果是默认的 22,可以不写。
    port    = ssh
  3. 粘贴完了以后,按下快捷键 Ctrl + X,再按一下字母 Y,然后敲击键盘回车键保存退出。

高级配置示例

保护 Web 服务(Nginx/Apache):

ini
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 3
bantime = 3600

[nginx-botsearch]
enabled = true
port = http,https
filter = nginx-botsearch
logpath = /var/log/nginx/access.log
maxretry = 5
bantime = 86400

保护 WordPress:

ini
[wordpress]
enabled = true
port = http,https
filter = wordpress
logpath = /var/log/nginx/access.log
maxretry = 3
bantime = 3600

保护 Postfix/Dovecot(邮件服务):

ini
[postfix]
enabled = true
port = smtp,ssmtp
filter = postfix
logpath = /var/log/mail.log

[dovecot]
enabled = true
port = pop3,pop3s,imap,imaps
filter = dovecot
logpath = /var/log/mail.log

配置参数详解

参数说明推荐值单位
bantime封禁时长86400(1天)或 3600(1小时)
findtime检测时间窗口600(10分钟)
maxretry最大失败次数3-5 次次数
ignoreip白名单 IP127.0.0.1/8 和你的固定 IPCIDR
backend日志监控后端auto(自动选择)-
usednsDNS 查询warn(警告但不阻止)-

封禁时间策略建议:

  • 首次违规:1 小时(3600 秒)
  • 重复违规:1 天(86400 秒)
  • 恶意攻击:1 周(604800 秒)或永久

步骤三:重启服务生效与日常查看

  1. 修改完了属于咱们自己的安全配置文件之后,我们需要告诉 Fail2ban 这位门卫大爷重新看一遍工作手册:

    bash
    systemctl restart fail2ban
  2. 为了保证无论重启服务器多少次它都在默默工作,随手允许它开机自启动:

    bash
    systemctl enable fail2ban

怎么查看它有没有在工作?抓到了几个坏人?

咱们可以通过它的客户端命令去查看目前有哪些因为爆破 SSH 被关进“小黑屋”的倒霉蛋。

bash
fail2ban-client status sshd

终端将会友好地输出一份短小的报告:

text
Status for the jail: sshd
|- Filter
|  |- Currently failed:	0         # 当前正在数错密码的次数(因为还没超过3次)
|  |- Total failed:	21            # 从服务开始到现在,这帮人一共输错了多少次密码
`- Actions
   |- Currently banned:	3         # 此刻正待在小黑屋里被封号的倒霉 IP 数量(被 ban 了!)
   |- Total banned:	5             # 历史总共拉黑过的倒霉蛋
   `- Banned IP list:	192.168.1.100 203.0.113.45 198.51.100.22  # 这里会列出被你封禁的详细 IP 地址

查看所有监狱状态

bash
# 列出所有启用的监狱
fail2ban-client status

# 输出示例:
# Status
# |- Number of jail:	3
# `- Jail list:	sshd, nginx-http-auth, wordpress

Fail2ban 日志管理

查看 Fail2ban 日志

bash
# 实时查看日志
tail -f /var/log/fail2ban.log

# 查看最近的封禁记录
grep "Ban" /var/log/fail2ban.log | tail -20

# 查看解封记录
grep "Unban" /var/log/fail2ban.log | tail -20

日志轮转配置

Fail2ban 自带日志轮转配置,通常位于 /etc/logrotate.d/fail2ban

bash
cat /etc/logrotate.d/fail2ban

典型配置:

/var/log/fail2ban.log {
    weekly
    rotate 4
    compress
    delaycompress
    missingok
    postrotate
        fail2ban-client flushlogs >/dev/null || true
    endscript
}

常用管理命令

封禁/解封 IP

bash
# 手动封禁 IP
fail2ban-client set sshd banip 192.168.1.100

# 手动解封 IP
fail2ban-client set sshd unbanip 192.168.1.100

# 解封所有 IP
fail2ban-client set sshd unbanip --all

查看封禁列表

bash
# 查看特定监狱的封禁 IP
fail2ban-client get sshd actionunbannedips

# 查看 iptables 规则
iptables -L f2b-sshd -n -v

重载配置

bash
# 重载所有监狱配置
fail2ban-client reload

# 重载特定监狱
fail2ban-client reload sshd

停止/启动服务

bash
# 停止 Fail2ban
systemctl stop fail2ban

# 启动 Fail2ban
systemctl start fail2ban

# 重启 Fail2ban
systemctl restart fail2ban

# 查看状态
systemctl status fail2ban

自定义过滤器(Filter)

如果内置过滤器不满足需求,可以创建自定义过滤器。

创建自定义过滤器

示例:保护自定义应用

  1. 创建过滤器文件:
bash
nano /etc/fail2ban/filter.d/myapp.conf
  1. 添加过滤规则:
ini
[Definition]
# 匹配失败登录的正则表达式
failregex = ^.*Failed login from <HOST>.*$
            ^.*Authentication failure.*from <HOST>.*$

# 忽略的行(可选)
ignoreregex =
  1. jail.local 中引用:
ini
[myapp]
enabled = true
port = 8080
filter = myapp
logpath = /var/log/myapp/access.log
maxretry = 3
bantime = 3600
  1. 重载配置:
bash
fail2ban-client reload

测试过滤器

bash
# 测试过滤器是否能正确匹配日志
fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf

# 输出会显示匹配的行数和示例

常见问题排查

Q1: Fail2ban 没有封禁任何 IP?

排查步骤:

  1. 检查服务状态
bash
systemctl status fail2ban
  1. 查看日志是否有错误
bash
tail -50 /var/log/fail2ban.log
  1. 确认监狱已启用
bash
fail2ban-client status sshd
  1. 检查日志路径是否正确
bash
# 查看 SSH 日志
tail -20 /var/log/auth.log

# 确认有失败登录记录
grep "Failed password" /var/log/auth.log
  1. 测试过滤器
bash
fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf

Q2: 误封了自己的 IP 怎么办?

解决方案:

bash
# 方法 1:从 VNC 控制台登录解封
fail2ban-client set sshd unbanip 你的IP

# 方法 2:临时停止 Fail2ban
systemctl stop fail2ban

# 方法 3:将自己的 IP 加入白名单
nano /etc/fail2ban/jail.local
# 在 ignoreip 中添加你的 IP
ignoreip = 127.0.0.1/8 ::1 你的IP/32

# 重载配置
fail2ban-client reload

预防措施:

  • 始终将自己的固定 IP 加入 ignoreip 白名单
  • 先测试配置,确认无误后再启用严格规则
  • 保留 VNC 控制台访问权限作为应急通道

Q3: 封禁时间太短/太长如何调整?

动态调整(无需重启):

bash
# 修改 SSH 监狱的封禁时间为 1 周
fail2ban-client set sshd bantime 604800

# 修改最大重试次数为 5
fail2ban-client set sshd maxretry 5

# 修改检测时间窗口为 20 分钟
fail2ban-client set sshd findtime 1200

永久修改: 编辑 /etc/fail2ban/jail.local,修改对应参数后重载。

Q4: 如何查看哪些 IP 正在尝试爆破?

bash
# 实时查看失败登录尝试
tail -f /var/log/auth.log | grep "Failed password"

# 统计最常见的攻击 IP
grep "Failed password" /var/log/auth.log | \
  awk '{print $(NF-3)}' | \
  sort | uniq -c | sort -rn | head -20

# 查看今天的攻击情况
grep "$(date +%b %e)" /var/log/auth.log | grep "Failed password"

Q5: Fail2ban 占用资源过高?

优化建议:

  1. 减少日志扫描频率
ini
# 在 jail.local 的 [DEFAULT] 部分添加
backend = systemd  # 使用 systemd journal 而非轮询文件
  1. 简化过滤器正则
  • 避免过于复杂的正则表达式
  • 使用 fail2ban-regex 测试效率
  1. 限制监狱数量
  • 只启用真正需要的监狱
  • 禁用不必要的监控
  1. 检查日志文件大小
bash
# 清理旧日志
journalctl --vacuum-time=7d

# 轮转大日志文件
logrotate -f /etc/logrotate.conf

Fail2ban 与其他安全工具配合

1. Fail2ban + SSH 密钥登录

最佳实践组合:

bash
# 1. 启用 SSH 密钥登录
# 2. 禁用密码登录
# 3. 修改 SSH 端口
# 4. 启用 Fail2ban 作为最后一道防线

2. Fail2ban + UFW 防火墙

bash
# UFW 负责基础端口管理
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

# Fail2ban 负责动态封禁恶意 IP
# 两者互补,提供多层防护

3. Fail2ban + Cloudflare

如果使用 Cloudflare CDN,需要特殊配置:

ini
# 在 jail.local 中添加
[DEFAULT]
# 信任 Cloudflare IP 段
ignoreip = 127.0.0.1/8 ::1 173.245.48.0/20 103.21.244.0/22 ...

# 使用 Cloudflare API 封禁 IP(需额外配置 action)
action = cloudflare

监控与告警

设置邮件告警

ini
# 在 jail.local 的 [DEFAULT] 部分添加
destemail = admin@example.com
sender = fail2ban@your-server.com
mta = sendmail
action = %(action_mwl)s  # 封禁时发送邮件并附带日志

使用 Telegram 机器人告警

创建自定义 action:

bash
nano /etc/fail2ban/action.d/telegram.conf
ini
[Definition]
actionstart =
actionstop =
actioncheck =
actionban = curl -s -X POST https://api.telegram.org/bot<TOKEN>/sendMessage \
            -d chat_id=<CHAT_ID> \
            -d text="🚨 Fail2ban: IP <ip> 已被封禁\n监狱: <name>\n原因: <failures> 次失败"
actionunban = curl -s -X POST https://api.telegram.org/bot<TOKEN>/sendMessage \
              -d chat_id=<CHAT_ID> \
              -d text="✅ Fail2ban: IP <ip> 已解封\n监狱: <name>"

最佳实践总结

安全配置清单

基础安全

Fail2ban 配置

监控与维护

推荐配置方案

个人博客/小型网站:

ini
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3

[sshd]
enabled = true

企业级服务器:

ini
[DEFAULT]
bantime = 86400
findtime = 600
maxretry = 3
ignoreip = 127.0.0.1/8 ::1 公司IP/32

[sshd]
enabled = true

[nginx-http-auth]
enabled = true

[wordpress]
enabled = true

有了 Fail2ban 坐镇你的服务器,你可以在面对日志里乱飞的牛鬼蛇神时,喝杯茶会心一笑了。☕✨


免责声明

本文仅供技术交流和学习参考,请遵守当地法律法规,合理合法使用网络服务。