增强服务器防御能力的自动化工具 Fail2Ban

作为一名站长,每天面对的都是一个充满风险的网络世界。在阴暗的角落里,总有一小撮人带着各种目的,对网络上的服务器发起攻击。这些攻击行为五花八门:有的在搜索站点漏洞,伺机入侵;有的通过非正常高频访问页面,耗尽服务器资源;还有的属于专门薅流量的灰色产业,紧盯网页上的媒体资源进行恶意抓取......因此,Web 服务器的安全防护话题愈发重要,甚至可以说已成为刚需。如何有效保护在线资源免受异常访问的侵扰,成为每一位站长必须直面的关键问题。本文将重点介绍服务器安全工具库中一款出色的开源工具------Fail2Ban,详细讲解其安装、使用方法,以及如何通过开箱即用的功能,为服务器筑起一道坚固的防线,减少攻击带来的影响。

使用 Fail2Ban 工具的前提

Fail2Ban 是基于Linux平台WebServer的一个插件,如果你的站点资源现托管在 Windows 服务器上的IIS上,而恰好又是基于单实例的架构,那么你需要对现有的Server 站点架构做一些改造。通常一个可靠的结构会包含一个前置的 Nginx 服务器用作反向代理或者负载均衡,后面则是负责站点资源托管的服务器或者集群。更进一步,为了增加整体可用性,前置反向代理会适当增加冗余备份等。不过这些不是我们今天主要讨论的话题。在完成上述改造后,在整个结构中,我们就有了一个 Linux + Nginx 的结构,这是我们开启 Fail2Ban 工具之旅的一个基础。

传统运维的弊端

传统的服务器安全运维,站长同学会定期人肉监控服务器各项状态,如 CPU、内存或者 DiskIO、数据库资源占用异常偏高,再或者在连接数释放不及时等导致的异常情况时,及时登到服务器上,查看最近访问日志中,识别存在明显攻击行为的访问,最终对这些 IP 或者 IP 段进行封禁,阻止后续的异常访问,降低服务器的非可控资源占用。但在典型的访问日志中,存在着以下问题:

  • 滞后性:通常只能在实际发生服务器性能明显下降时,开始干预,此时给正常的客户提供的服务已经或多或少的受到了影响,服务质量下降。
  • 需要纯人工,或者借助一些其他三方工具从海量的日志中分析明显不正统的流量,耗时、费力
  • 国内很多服务器的 IP 是动态获取的,攻击流量存在一定的时效性,可能一段时间内使用 A 地址扫描网站,再过 24 小时会自动变成地址 B,封禁、解封存在着时效性,会存在误伤的可能

因此,亟需一种可以能够可以识别攻击行为、阻止异常访问的自动化工具参与到日常运维中来。

Fail2Ban 的核心原理

Fail2Ban 之所以能成为服务器安全的得力助手,核心在于其动态监控的防护机制。它会持续监控服务器的各类日志文件(如 SSH 登录日志、Web 服务器访问日志等),通过预设的规则识别异常访问行为。当某一 IP 地址的违规次数达到设定阈值时,Fail2Ban 会自动调用防火墙(如 iptables、firewalld 等)对该 IP 进行临时或永久封禁,从而阻止其继续发起攻击,降低服务器资源被进一步消耗。这种机制的优势在于灵活性和实时性。它不局限于特定的攻击类型,只要能在日志中体现出异常特征,就能有效拦截。同时,临时封禁的设置也避免了误封正常用户后难以恢复的问题。

Fail2Ban 的安装步骤

不同的操作系统,Fail2Ban 的安装方式略有差异,以下是几种常见系统的安装方法:

  • Ubuntu/Debian 系统 :在终端中输入命令 sudo apt-get update 更新软件源,然后执行 sudo apt-get install fail2ban 即可完成安装,安装过程中,系统会自动处理依赖关系,无需额外操作。
  • CentOS/RHEL 系统 :由于 CentOS 默认的软件源中可能没有 Fail2Ban,需要先安装 EPEL 源。输入 sudo yum install epel-release 安装 EPEL 源,之后再运行 sudo yum install fail2ban 进行安装。
  • Fedora 系统 :直接在终端中输入 sudo dnf install fail2ban 即可安装,Fedora 的软件源中通常包含 Fail2Ban。

安装完成后,可以通过 sudo systemctl start fail2ban 启动服务,再用 sudo systemctl enable fail2ban 设置开机自启动,确保服务器重启后 Fail2Ban 能自动运行。

后面我们将以Ubuntu为例,讲解Fail2Ban的核心功能配置。

Fail2Ban 的核心功能配置

Fail2Ban 的配置文件主要位于 /etc/fail2ban/ 目录下,其中 jail.conf 是主要的配置文件,Fail2Ban 支持针对不同的服务进行配置,如 SSH、Apache、Nginx 等。每个服务都有自己的配置段落,例如 SSH 服务的配置段落为 [sshd],Apache 服务的配置段落为 [apache] 等,Nginx WebService有[nginx] 的相应配置。

但为了避免升级时配置被覆盖,建议先创建自定义配置文件jail.local 并在其中进行自定义配置。在 jail.local 中,你可以根据需要标记自定义服务的防护,以及调整其相关参数。

  • 基本设置 :在 jail.local 中,可以设置默认的封禁时间(bantime )、触发封禁的最大尝试次数(maxretry )以及检测时间窗口(findtime )。例如,将 bantime = 3600 设置为封禁 1 小时,maxretry = 5 表示 5 次失败尝试后触发封禁,findtime = 600 意味着在 10 分钟内的失败尝试会被累计。
  • 针对特定服务的配置 :Fail2Ban 支持对多种服务进行防护,如 SSH、Apache、Nginx 等。以 SSH 为例,在配置文件中找到 [sshd] 部分,将 enabled = true 开启防护,还可以根据实际情况调整该服务的 maxretrybantime 等参数。
  • 邮件通知设置 :如果希望在有 IP 被封禁时收到邮件通知,可以配置 destemail(目标邮箱)、sendername(发件人名称)等参数,并确保服务器已安装邮件发送工具(如 sendmail )。

如,某天我们Nginx WebServer 出现了异常多的 404 错误请求,虽然我们在一定程度上允许WebServer 有合理范围的404错误请求,但如果超出了一定的度,势必会造成服务器资源的过度消耗,所以这里超出范围的规则,就需要我们在 jail.local 中合理的添加配置去封禁这些 "恶意" 发起IP:

先在 /etc/fail2ban/filter.d/ 目录下创建一个自定义的过滤器文件 nginx-ban-404ips.conf,内容如下:

ini 复制代码
[Definition]
failregex = ^<HOST> - .* "GET .* HTTP/1\..*" 404 .*$
ignoreregex =

再在jail.local中添加如下配置,启用上面我们定义的过滤器:

ini 复制代码
[nginx-ban-404ips]
enabled = true
filter = nginx-ban-404ips # 声明前面定义的 nginx-ban-404ips 过滤器
logpath = /var/log/nginx/access.log # nginx访问日志路径
maxretry = 5 # 最大重试次数
findtime = 600 # 检测时间窗口
bantime = 3600 # 封禁时长

该配置实现了如下自动化机制:

当某个 IP 在指定时间内(10 分钟)对服务器发起的 HTTP/HTTPS 请求中,有 5 次及以上返回 "404 Not Found" 错误时,fail2ban会自动通过 iptables 防火墙封禁该 IP,封禁时长为 1 小时(3600 秒)。

配置完成后,需要通过 sudo systemctl restart fail2ban 重启服务,使配置生效。这样就很方便实现了通过预定义的过滤器,来自动封禁异常行为访问。

实际场景演练

在完成 Fail2Ban 基础安装与核心功能配置后,一般我们通过 bantime(封禁时长 )、maxretry(最大重试次数 )、findtime(检测时间窗口 )等关键配置,即可应对较为常见的攻击场景。后面我们会模拟不同的攻击场景,详解如何自动化防护:

一、核心配置介绍

属性名 功能介绍 示例
bantime 判定攻击后,封禁 IP 的时长(秒),可设永久封禁(如 bantime = -1 bantime = 3600(封禁3600秒/1小时)
maxretry 检测时间窗口内,IP 触发规则的最大异常次数,超过则封禁 maxretry = 5(5次尝试)
findtime 统计异常行为的时间窗口(秒),若 IP 在此窗口内触发 maxretry 次则封禁 findtime = 600(600秒/10分钟)

二、场景模拟与配置实践

场景1:零散 IP 大量访问无特征页面

攻击特征 :大量随机 IP 短时间内,对网站普通页面(如首页、产品列表页)高频访问,无固定路径规律,消耗带宽与服务器连接数。
配置思路 :通过 findtime 缩小检测窗口、maxretry 降低触发阈值,快速拦截零散试探。

在 /etc/fail2ban/filter.d/ 目录下新建 nginx-noscene.conf Filter 文件

ini 复制代码
[Definition]  
# 匹配任意路径的高频访问(日志格式为 Nginx 标准访问日志)  
# 示例日志:1.2.3.4 - - [01/Jan/2024:12:00:00 +0800] "GET /random-page HTTP/1.1" 200 1234  
failregex = ^<HOST> .* "GET .* HTTP/1\.[01]" .*$  
            ^<HOST> .* "POST .* HTTP/1\.[01]" .*$  

ignoreregex =   

jail.local添加配置:

ini 复制代码
# 假设防护 Nginx 普通访问,在 jail.local 新增 [nginx-noscene] 配置  
[nginx-noscene]  
enabled = true  
filter = nginx-noscene  # 调用默认 Nginx 异常请求过滤规则,可自定义  
logpath = /var/log/nginx/access.log  # 需替换为实际 Nginx 访问日志路径  
bantime = 1800  # 封禁30分钟,给零散 IP 短暂惩罚,避免误封长期影响  
maxretry = 10   # 10分钟(findtime)内超10次访问即判定攻击  
findtime = 600  

配置原因 :零散 IP 攻击分散但高频,缩短 findtime 让检测更灵敏,适度降低 maxretry 覆盖 "小额多次" 试探;bantime 设为 30 分钟,平衡拦截效率与误封恢复周期。

场景2:异常 IP 访问敏感页面(login/admin 等)

攻击特征 :大量未知 IP 高频访问登录页(/login )、管理后台(/admin )、密码重置页(/password ),尝试暴力破解或探路。
配置思路 :针对敏感路径单独配置规则,缩小 findtime、降低 maxretry,快速拦截试探。

在 /etc/fail2ban/filter.d/ 目录下新建 nginx-sensitive.conf

ini 复制代码
[Definition]  
failregex = ^<HOST> .* "GET /(login|admin|password) HTTP/1\.[01]" .*$  
            ^<HOST> .* "POST /(login|admin|password) HTTP/1\.[01]" .*$  


ignoreregex = 

jail.local添加配置:

ini 复制代码
[nginx-sensitive]  
enabled = true  
filter = nginx-sensitive  
logpath = /var/log/nginx/access.log  
bantime = 3600  # 封禁1小时,给暴力破解类攻击及时惩罚  
maxretry = 3    # 10分钟内超3次访问敏感页即触发  
findtime = 300  # 缩短检测窗口至5分钟,快速响应高频试探  

配置原因 :敏感页面是攻击重灾区,findtime 缩短让检测更实时,maxretry 设为 3 严格限制尝试次数;bantime 封禁1小时,既拦截攻击,也避免正常用户偶尔误操作被长期封禁。

场景3:雷同 UA 洪水攻击

攻击特征 :大量请求使用相同或高度雷同的 User-Agent(UA),如伪装成搜索引擎爬虫(Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html) ),但行为异常(短时间内遍历页面、请求频率异常)。
配置思路 :自定义 filter 规则匹配雷同 UA,结合 findtimemaxretry 限制频率。

/etc/fail2ban/filter.d/ 目录下新建 nginx-ua-flood.conf

ini 复制代码
[Definition]  
failregex = ^.*"(?P<ua>Mozilla/5.0 \(compatible; Baiduspider/2.0; .*\))".*$  

jail.local添加配置:

ini 复制代码
[nginx-ua-flood]  
enabled = true  
filter = nginx-ua-flood  # 调用自定义 UA 过滤规则  
logpath = /var/log/nginx/access.log  
bantime = 10800  # 封禁3小时,针对批量 UA 攻击延长惩罚  
maxretry = 5     # 10分钟内超5次雷同 UA 请求触发  
findtime = 600  

配置原因 :雷同 UA 攻击易伪装、规模大,自定义 filter 精准识别 UA 特征;bantime 延长可减少同一批 UA 短时间内反复攻击;maxretry 控制触发门槛,避免单 IP 正常浏览被误封。

场景4:用户尝试登录服务器(SSH 暴力破解)

除监控WebServer外,Fail2ban还可监控Server的SSH服务。下面简单介绍如何监控SSH日志,自动封禁异常IP,减少因暴力破解而导致的密码泄露。

攻击特征 :大量 IP 尝试 SSH 登录,密码错误日志高频出现(如 /var/log/auth.logFailed password for root from... )。
配置思路 :利用 Fail2Ban 默认 sshd 规则,调整 bantimemaxretry 适配服务器安全策略。

ini 复制代码
# 编辑 jail.local 中添加 [sshd] 配置  
[sshd]  
enabled = true  
bantime = 86400  # 封禁1天,对 SSH 暴力破解重罚  
maxretry = 3     # 10分钟内3次密码错误即触发  
findtime = 600  

配置原因 :SSH 是服务器核心入口,暴力破解风险极高。maxretry 设为 3 严格限制尝试次数,bantime 设1天,大幅增加攻击成本;findtime 保持10分钟,覆盖典型暴力破解的试探周期。

注:这里没有显式指定ssh的logpath,是因为fail2ban默认包含了用于[sshd]的过滤器,过滤器已中已经包含了 /var/log/auth.log这个文件,所以这里无需显式指定,这需要关注访问行为设置规则配置即可。

Fail2Ban 的其他技巧

  • 查看封禁列表 :使用命令 sudo fail2ban-client status 自定义过滤器可以查看当前被封禁的 IP 地址以及相关状态信息,便于了解服务器的受攻击情况。
  • 手动封禁 IP :如果发现个别 IP 被规则遗漏,可以执行 sudo fail2ban-client set 自定义过滤器 banip 192.168.1.1(封禁 192.168.1.1)。
  • 解除误封 IP :如果发现正常 IP 被误封,可以执行 sudo fail2ban-client set 自定义过滤器 unbanip 192.168.1.1(解除封禁 192.168.1.1 )。

通过以上场景演练,可精准调控 Fail2Ban 核心参数,针对如上场景构建防护网。关键在于理解 bantime 控制惩罚力度、maxretry 定义触发门槛、findtime 划定检测范围,结合日志特征与攻击模式灵活和动态的调整配置,让服务器防御既 "精准打击" 又 "容错可控"。站长可以大幅提升服务器的安全性,有效抵御各类网络攻击,为网站的稳定运行提供有力保障。

参考文档

Fail2Ban 项目 Github 官方地址:https://github.com/fail2ban/fail2ban