入侵防御软件框架Fail2ban使用学习笔记

什么是 Fail2ban?

Fail2ban 是一个入侵防御软件框架,用于保护服务器免受暴力破解和其他自动化攻击。它通过监控系统日志(如 /var/log/auth.log/var/log/nginx/error.log 等)来检测恶意行为,例如多次失败的登录尝试。一旦检测到异常,它会自动调用防火墙规则(如 iptables, nftables, firewalld 等)来封锁可疑的IP地址一段时间。

核心概念

Jail(监禁): 核心概念。一个“Jail”定义了一个应用场景,它指定了:

要监控什么日志logpath

用什么规则来检测恶意行为filter

检测到后执行什么动作action

封禁多长时间bantime

触发封禁的阈值maxretryfindtime

Filter(过滤器): 包含一组正则表达式规则的文件(位于 /etc/fail2ban/filter.d/),用于解析日志文件并识别失败的尝试。例如 sshd, nginx-http-auth

Action(动作): 定义当达到封禁条件时要执行的命令的文件(位于 /etc/fail2ban/action.d/)。通常是添加一条防火墙规则来封禁IP。动作也包括解封时的命令。

Jail.conf / Jail.local: 主配置文件。绝对不要直接修改 jail.conf,因为软件更新时会覆盖它。应该使用 jail.local 文件来覆盖默认设置。配置是分层级的:[DEFAULT] 段设置全局默认值,后面的 [jail-name] 段为特定服务设置。

第一部分:安装与基本使用

1. 安装 Fail2ban

在大多数 Linux 发行版上,安装都非常简单。
Ubuntu / Debian:

sudo apt update
sudo apt install fail2ban

CentOS / RHEL / Fedora:

# CentOS/RHEL (需要EPEL仓库)
sudo yum install epel-release
sudo yum install fail2ban

# Fedora
sudo dnf install fail2ban

安装后,Fail2ban 会自动启动并启用开机自启。 您可以通过以下命令检查状态:

sudo systemctl status fail2ban

2. 基本配置:创建 jail.local

复制默认的配置文件并进行自定义:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

用您喜欢的文本编辑器(如 nanovim)打开 jail.local

sudo nano /etc/fail2ban/jail.local

3. 配置全局默认值 ([DEFAULT] 段)

在 [DEFAULT] 部分,您可以设置所有Jail的默认值。以下是一些关键参数:

[DEFAULT]
# 忽略的IP地址范围(白名单),多个IP用空格分隔
ignoreip = 127.0.0.1/8 192.168.1.0/24 123.45.67.89

# 封禁时间(秒)。负数表示“永久封禁”,请谨慎使用。
bantime  = 3600

# 时间窗口(秒),在此时间内达到最大重试次数则触发封禁。
findtime  = 600

# 最大重试次数。
maxretry = 5

# 使用的防火墙后端(通常自动检测,无需修改)
# banaction = iptables-multiport

4. 启用和配置特定的 Jail

在 jail.local 文件中,继续往下翻,您会看到很多预定义的 Jail(如 [sshd][apache-auth]),它们默认都是被注释(禁用)的。

要启用一个 Jail,只需取消对应段的注释并将其 enabled 选项设为 true

示例 1:启用 SSH 保护(这是最常用的)

[sshd]
enabled = true
# 您还可以为此Jail单独设置参数来覆盖DEFAULT值
port    = ssh
logpath = %(sshd_log)s
maxretry = 3
bantime  = 86400 # 封禁24小时

示例 2:启用 Nginx 认证保护(防止登录页面被爆破)

[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log

示例 3:启用 WordPress 保护(需要先配置 filter)
这需要额外的过滤器来匹配 WordPress 的登录尝试(通常是 wp-login.php)。

[wordpress]
enabled  = true
port     = http,https
logpath  = /var/log/nginx/*access.log # 或 Apache 的 access.log
maxretry = 3

注意:对于像 WordPress 这样的Web应用,确保您有对应的过滤器文件(/etc/fail2ban/filter.d/wordpress.conf)。Fail2ban 默认可能不提供,需要自行创建或从社区获取。

5. 重启 Fail2ban 以使配置生效

每次修改配置文件后,都需要重启服务:

sudo systemctl restart fail2ban

第二部分:常用命令与管理

Fail2ban 提供了客户端工具 fail2ban-client 来交互和管理。

    1. 查看状态: 查看所有启用的 Jail 及其状态。

      sudo fail2ban-client status
    2. 查看特定 Jail 的详细状态: 查看某个 Jail(如 sshd)封禁了哪些IP。
      sudo fail2ban-client status sshd

      输出示例:

      Status for the jail: sshd
      |- Filter
      | |- Currently failed: 1
      | |- Total failed: 15
      | `- File list: /var/log/auth.log
      `- Actions
      |- Currently banned: 2
      |- Total banned: 5
      `- Banned IP list: 123.45.67.89 101.102.103.104
    3. 手动封禁一个IP
      sudo fail2ban-client set <jail-name> banip <ip-address>
      # 示例
      sudo fail2ban-client set sshd banip 202.54.1.1
    4. 手动解封一个IP
      sudo fail2ban-client set <jail-name> unbanip <ip-address>
      # 示例
      sudo fail2ban-client set sshd unbanip 202.54.1.1
    5. 解封所有IP
      sudo fail2ban-client set <jail-name> unban --all

      第三部分:高级配置与自定义

      1. 自定义过滤器 (Filter)

      有时默认的过滤器可能不匹配您的日志格式,您需要自定义。

      例如,为自定义服务创建过滤器:

        1. 创建过滤器文件:

          sudo nano /etc/fail2ban/filter.d/my-service.conf
        2. 编写规则。一个简单的示例:

          [Definition]
          failregex = ^.*Failed login from <HOST>.*$ # 这是一个示例,请根据您的实际日志编写正则表达式
          ignoreregex =
          <HOST> 是一个关键标签,用于匹配IP地址。
        3. 在 jail.local 中创建一个新的 Jail 来使用这个过滤器:
          [my-service]
          enabled = true
          port = 12345
          filter = my-service
          logpath = /var/log/my-service.log
          maxretry = 3

          调试过滤器:使用 fail2ban-regex 工具测试您的过滤器是否正确。

          fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf

          2. 自定义动作 (Action)

          您可以定义更复杂的动作,例如发送邮件通知或调用Webhook。

          示例:封禁时发送邮件

          1. 确保系统安装了邮件工具(如 sendmail)。

          2. 在 jail.local 中修改动作:

          [sshd]
          enabled = true
          action = %(action_mwl)s # 默认动作是 iptables-multiport,`mwl` 表示 Mail Whois Lookup(发送邮件、whois查询、并记录)

          您也可以完全自定义:

          action = iptables-multiport[name=SSH, port="ssh", protocol="tcp"]
                   sendmail[name=SSH, dest="your-email@example.com", sender="fail2ban@yourserver.com"]

          3. 防止误封:使用 Ignoreip 和更精细的 Filter

          务必使用 ignoreip 将您自己的IP地址、局域网IP和其他可信IP加入白名单,以免不小心把自己锁在外面。

          第四部分:故障排除与日志

          • 查看 Fail2ban 的日志:这是排查问题的第一站。

            sudo tail -f /var/log/fail2ban.log
          • 检查防火墙规则:Fail2ban 通过操作防火墙规则工作,直接查看规则是确认它是否生效的好方法。
            # 如果使用 iptables
            sudo iptables -L -n
            # 或者查看 f2b- 开头的链
            sudo iptables -L f2b-sshd -n
          • 确保日志路径正确:在 Jail 配置中指定的 logpath 必须绝对正确。检查文件是否存在。

          总结

          Fail2ban 是一个“设置后就不用管”的强大安全工具,但初始配置需要细心:

          1. 安装 Fail2ban。

          2. 创建 jail.local 并配置全局 [DEFAULT] 设置(尤其是 ignoreip!)。

          3. 启用 您需要的 Jail(如 [sshd])。

          4. 根据需要自定义 Filter 和 Action。

          5. 重启 Fail2ban 服务。

          6. 使用 fail2ban-client 命令进行管理和监控

          7. 遇到问题时查看 /var/log/fail2ban.log

          通过合理配置,Fail2ban 可以极大地提高服务器对自动化攻击的抵抗力,让您的系统更加安全。

          配置方案实例

          保护您的网站(日志文件为 /home/wwwlogs/www.123ppp.com.log)免受恶意IP的请求。默认的 jail.conf 提供了基础,默认配置是很好的参考,但直接修改它会被更新覆盖。正确的做法是创建 jail.local 来覆盖和添加自定义配置。我们需要自定义一个专属的Jail

          创建一个新的Jail,并为其配置一个合适的过滤器(Filter)。以下是详细步骤:

          第1步:创建或编辑 jail.local 文件

          sudo nano /etc/fail2ban/jail.local

          第2步:写入以下配置内容

          将下面的配置添加到您的 jail.local 文件中。这段配置做了以下几件事:

          1. 在 [DEFAULT] 部分设置了全局规则(如白名单IP、封禁时间等)。

          2. 创建了一个名为 [nginx-bad-request] 的新Jail(名字您可以自己定)来监控您的特定日志文件。

          [DEFAULT]
          ignoreip = 127.0.0.1/8 ::1
          bantime = 3600
          findtime = 600
          maxretry = 5
          banaction = iptables-multiport
          
          # 更全面的基础防护网,它能捕捉到更多种类的异常行为
          [ip-range-monitor]
          enabled = true
          logpath = /home/wwwlogs/www.123ppp.com.log
          filter = nginx-ip-range
          maxretry = 100 # 提高触发阈值,允许更多的偶发性错误
          findtime = 600 # 延长统计时间窗口到10分钟,观察更长时间段的行为
          bantime = 1800 # 缩短首次封禁时间为30分钟,对于首次违规者惩罚稍轻
          bantime.increment = true # 启用增量封禁
          bantime.factor = 1.5 # 每次封禁时间乘以1.5倍
          bantime.maxtime = 604800 # 最长封禁时间:一周(7天*24小时*3600秒)
          bantime.rndtime = 600 # 添加一个随机时间(0-600秒),避免攻击者精确计算解封时间
          port = http,https
          banaction = iptables-ipset-proto6
          
          # 更精准的强化防护,它专门针对已知的、特定类型的攻击手法,误报率极低
          [nginx-bad-request-range]
          enabled = true
          logpath = /home/wwwlogs/www.123ppp.com.log
          filter = nginx-bad-request
          maxretry = 5
          findtime = 180
          bantime = 3600
          bantime.increment = true
          bantime.factor = 2
          bantime.maxtime = 604800
          bantime.rndtime = 300 #在固定的封禁时间基础上,随机增加最多300秒(5分钟)的额外封禁时间
          port = http,https
          banaction = iptables-ipset-proto6 #必须确保系统已经安装并正确配置了 ipset 工具
          
          # 封禁特定User-Agent,封禁这些特定的爬虫
          [nginx-bad-bots]
          enabled = true
          logpath = /home/wwwlogs/www.123ppp.com.log
          filter = nginx-bad-bots
          maxretry = 1 # 发现一次就封
          bantime = 604800 # 封禁一周
          port = http,https
          

          对于iptables-ipset-proto6的说明:

          iptables-ipset-proto6 是什么?

          这是一个 Fail2ban 的动作(action),它定义了如何执行封禁。

          它的工作流程是:当需要封禁一个 IP 时,Fail2ban 不会直接创建一条 iptables 规则,而是会调用 ipset 工具,将这个 IP 添加到一个预定义的集合(set) 中。

          然后,只需要一条 iptables 规则来匹配整个这个 IP 集合即可。这比传统为每个IP创建一条iptables规则的方式效率高几个数量级。

          为什么必须安装 ipset

          这个动作(action)的本质是一系列封装好的 shell 命令,其中核心命令就是 /usr/sbin/ipset

          如果系统里没有 ipset 这个程序,Fail2ban 尝试执行封禁时,就会在日志中看到类似 ERROR - Failed to execute ban jail 'ip-range-monitor' action 'iptables-ipset-proto6' 的错误,并且提示 ipset 命令未找到。

          iptables-ipset-proto6iptables-ipset 的区别?

          iptables-ipset-proto6:是 iptables-ipset 的增强版,同时支持 IPv4 和 IPv6。这是现代环境下的推荐选择。

          iptables-ipset:通常只支持 IPv4。

          如果你的服务器不需要处理 IPv6 流量,两者都可以。但为了更好的兼容性,通常直接使用 iptables-ipset-proto6 更省心。

          ipset的安装和验证

          1. 安装 ipset
          根据你的 Linux 发行版使用对应的包管理工具安装:

          # 对于 CentOS / RHEL / RockyLinux / AlmaLinux
          sudo yum install ipset
          # 或使用 dnf(新版本)
          sudo dnf install ipset
          
          # 对于 Debian / Ubuntu
          sudo apt update
          sudo apt install ipset

          验证 ipset 是否安装成功
          安装后,检查一下 ipset 命令是否可用:

          ipset --version

          如果显示出版本信息(如 v7.15),说明安装成功。

          3. 重启 Fail2ban 服务
          安装完 ipset 后,最好重启 Fail2ban 服务以确保它能够正确识别和使用新的依赖。

          sudo systemctl restart fail2ban

          检查 Fail2ban 状态和日志
          重启后,检查 Fail2ban 的状态和日志,确认没有报错:

          # 查看服务状态
          sudo systemctl status fail2ban
          
          # 查看指定 jail 的状态
          sudo fail2ban-client status ip-range-monitor
          
          # 查看 Fail2ban 日志(通常有最新错误信息)
          sudo tail -f /var/log/fail2ban.log

          如果日志中没有关于 ipset 命令未找到的错误,并且 Jail 状态为 Active,说明配置成功。
          总结

          配置项 依赖 后果
          banaction = iptables-ipset-proto6 必须安装 ipset 未安装则封禁功能失效,Fail2ban 会报错。
          banaction = iptables-multiport (默认) 仅依赖 iptables 系统通常预装,但性能不如 ipset。

          结论:为了使用 iptables-ipset-proto6 这个高性能的封禁动作,安装 ipset 是必要的前提条件。 安装过程非常简单,完成后能极大提升 Fail2ban 在应对大量攻击 IP 时的性能。

          第3步:创建自定义过滤器(Filter)

          Fail2ban依靠过滤器文件中的正则表达式来识别日志中的恶意行为。我们需要为您的日志创建一个。

          1. 创建过滤器文件:

            vim /etc/fail2ban/filter.d/nginx-bad-request.conf
          2. 写入过滤规则。根据日志样例,写一个通用且有效的规则,用于更精准的强化防护,它专门针对已知的、特定类型的攻击手法,误报率极低。
          [Definition]
          failregex = ^<HOST> -.*"(GET|POST|HEAD).*\.(php|asp|env).*HTTP.*"\s404\s.*$
                      ^<HOST> -.*"(GET|POST|HEAD).*(\/wp-admin|\/admin).*HTTP.*"\s404\s.*$
                      ^<HOST> -.*"(GET|POST|HEAD).*\/config\.php.*HTTP.*"\s404\s.*$
                      ^<HOST> -.*"(GET|POST|HEAD).*HTTP.*"\s(400|403|499)\s.*$
                      ^<HOST> -.*"(GET|POST|HEAD).*HTTP.*"\s(4[0-35-9]\d|50\d)\s.*$
          
          ignoreregex = \.(jpg|jpeg|png|gif|webp|css|js|ico|svg|woff2?|ttf|eot|otf)(\?.*)?\sHTTP.*\s404\s
                        \/(robots\.txt|favicon\.ico)(\?.*)?\sHTTP.*\s404\s
          
          #下面注释掉的是:用!(非)的方式来限定某些ip段。先记上,以便需要时用。
          #ignoreregex = ^(?!34\.174\.|172\.70\.|172\.69\.|162\.158\.)
          

           

          注意<HOST>是一个关键标签,Fail2ban靠它来识别IP地址。

          再建另一个过滤器文件,它能更全面的基础防护网,它能捕捉到更多种类的异常行为

          vim /etc/fail2ban/filter.d/nginx-ip-range.conf

           

          [Definition]
          failregex = ^<HOST> -.*"(GET|POST|HEAD).*HTTP.*"\s[4-5][0-9][0-9]\s.*$
          ignoreregex = .*\.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg)$.*\s404\s
          
          #下面注释掉的是:用!(非)的方式来限定某些ip段。先记上,以便需要时用。
          #ignoreregex = ^(?!34\.174\.|172\.70\.|172\.69\.|162\.158\.)
          

          过滤器规则解释

          这个配置专门针对以下几种恶意行为:

          1. 常见错误状态码(404|400|403|499) – 封禁产生大量”未找到”、”错误请求”、”禁止访问”等错误的IP。

          2. PHP文件探测\.php – 攻击者常尝试访问不存在的php文件来探测漏洞。

          3. ASP文件探测\.asp – 针对Windows服务器的探测。

          4. 后台管理目录扫描\/wp-admin 和 \/admin – 尝试寻找网站后台入口。

          5. 敏感文件扫描\/\.env 和 \/config\.php – 尝试获取配置文件。

          第4步:测试过滤器(非常重要!)

          在重启Fail2ban之前,请务必测试您的过滤器是否能正确匹配日志中的恶意行。

          sudo fail2ban-regex /home/wwwlogs/www.123ppp.com.log /etc/fail2ban/filter.d/nginx-bad-request.conf

          如果输出中显示有匹配的条目(如 Matched: 10),说明配置成功。如果显示 0 matched,则需要调整您的 failregex

           

          第5步:配置完成后,重启Fail2ban并检查状态,务必执行以下命令:

          # 检查配置文件语法是否正确
          fail2ban-client -t
          
          # 重载 Fail2ban 配置使其生效
          systemctl reload fail2ban
          
          # 查看该 Jail 的状态,确认它已正常运行并监控日志,这个命令会显示该Jail目前已经封禁了哪些IP地址。
          fail2ban-client status ip-range-monitor

          总结与建议

          1. 不要修改默认的 jail.conf:始终在 jail.local 和 /etc/fail2ban/filter.d/ 目录下进行自定义配置。

          2. 核心是过滤器:上面的 failregex 是一个通用规则。要获得最佳效果,您最好提供一段真实的恶意访问日志样例,这样可以编写出更精确的过滤规则。

          3. 调试工具fail2ban-regex 命令是您调试过滤器的最好朋友,一定要善用它。

          4. 观察日志:配置完成后,可以实时查看Fail2ban的日志来观察封禁情况:

          sudo tail -f /var/log/fail2ban.log

          高级技巧:封禁特定User-Agent

          从日志中可以看到一些爬虫(如SemrushBotGPTBot)。如果您想封禁这些特定的爬虫,可以创建另一个过滤器:

          vim /etc/fail2ban/filter.d/nginx-bad-bots.conf

          内容:

          [Definition]
          failregex = ^<HOST> -.*"GET.*HTTP.*".*"(.*(SemrushBot|GPTBot|AhrefsBot).*)"$
          

          然后在 jail.local 中启用它:

          [nginx-bad-bots]
          enabled  = true
          logpath  = /home/wwwlogs/www.123ppp.com.log
          filter   = nginx-bad-bots
          maxretry = 1  # 发现一次就封
          bantime  = 604800  # 封禁一周
          port     = http,https

          最终建议

          1. 先测试再启用:使用 fail2ban-regex 命令充分测试您的过滤器,确保不会误封正常用户。

          2. 逐步调整:开始时可以设置较短的封禁时间(如1小时),观察效果后再调整。

          3. 监控日志:封禁后查看 /var/log/fail2ban.log 确认效果。

          这个配置将能有效防御日志中显示的各种扫描器和恶意爬虫,显著提升您的网站安全性。

          补充资料

          使用 ignoreip 参数让来自搜索引擎官方IP的请求不被封禁
          操作步骤:
          1. 获取搜索引擎官方IP段
          您需要找到Google、Bing、Baidu等搜索引擎公布的爬虫IP地址段。这需要定期维护更新。

          Googlebot: 来自 https://developers.google.com/search/apis/ipranges/googlebot.json 或执行 nslookup -type=PTR googlebot.com 并反向解析您日志中看到的Googlebot IP。

          Bingbot: 官方文档或通过 nslookup search.msn.com 等方式获取。

          Baiduspider: 官方公布或通过日志分析。

          2. 将IP段添加到Jail配置的 ignoreip 中

          编辑您的 Jail 配置文件(/etc/fail2ban/jail.local):

          [ip-range-monitor]
          enabled = true
          logpath = /home/wwwlogs/www.123ppp.com.log
          filter = nginx-ip-range
          maxretry = 30
          findtime = 300
          bantime = 3600
          port = http,https
          banaction = iptables-ipset-proto6
          
          # 正确的方式:在这里添加IP白名单
          ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24
          # 添加搜索引擎IP段示例(请替换为真实的最新IP段)
          ignoreip = 66.249.64.0/19 66.249.80.0/20  # Googlebot
          ignoreip = 157.55.0.0/16 199.30.27.0/24    # Bingbot
          ignoreip = 119.63.192.0/21 180.76.0.0/16   # Baiduspider
          # ... 可以继续添加其他引擎的IP段

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部