
Fail2ban 安装与使用终极笔记
摘要
本文档旨在提供一个在主流 Linux 服务器 (CentOS/RHEL, Debian/Ubuntu) 上安装、配置和管理 Fail2ban 的完整指南。Fail2ban 是一个入侵防御软件框架,通过监控日志文件,匹配恶意行为模式(如密码暴力破解、漏洞扫描等),并自动调用系统防火墙封禁相应的IP地址。
1. 安装 Fail2ban
根据您的 Linux 发行版,选择对应的安装命令。
选项 A: 在 CentOS / RHEL 系统上
在基于 Red Hat 的系统中 (如 CentOS 7/8/9, RHEL),Fail2ban 不在默认软件源中,需要先安装 EPEL (Extra Packages for Enterprise Linux) 扩展源。
# 步骤 1.1: 安装 EPEL 源sudo yum install -y epel-release
# 步骤 1.2: 安装 Fail2bansudo yum install -y fail2ban
选项 B: 在 Debian / Ubuntu 系统上
在基于 Debian 的系统中 (如 Debian 10/11/12, Ubuntu 18.04/20.04/22.04),Fail2ban 位于官方默认源中,可以直接安装。
# 步骤 1.1: 更新软件包列表 (最佳实践)sudo apt update
# 步骤 1.2: 安装 Fail2bansudo apt install -y fail2ban
步骤 1.3: 启动并设置开机自启 (所有系统通用)
现代的 Linux 发行版都使用 systemd
来管理服务,因此以下命令是通用的。
# 立即启动 Fail2ban 服务sudo systemctl start fail2ban
# 将 Fail2ban 服务设置为开机自启sudo systemctl enable fail2ban
步骤 1.4: 验证服务状态 (所有系统通用)
检查服务是否已成功启动并处于 active (running)
状态。
# 查看 Fail2ban 服务的当前状态sudo systemctl status fail2ban
成功标志:看到绿色的
active (running)
字样。
2. 核心配置
Fail2ban 的配置遵循“覆盖”原则,我们绝对不要修改主配置文件 jail.conf
,而应在 jail.local
中进行所有自定义。
步骤 2.1: 创建本地配置文件
复制一份 jail.conf
作为我们的本地配置文件 jail.local
。
# 从模板复制配置文件sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
步骤 2.2: 编辑 jail.local
文件
使用文本编辑器(如 nano
或 vim
)打开 jail.local
文件进行配置。
sudo nano /etc/fail2ban/jail.local
步骤 2.4: 粘贴您的自定义配置
将文件原有内容清空,然后粘贴您自己的配置。
# =================================================================================# Fail2ban Ultimate Configuration - v3.3 (Final Stability-Focused Version)# 修正了“日志文件未找到”的启动错误,采用最稳妥的日志路径# =================================================================================
[DEFAULT]# --- 全局默认设置 ---# 这些设置将应用于所有未明确覆盖它们的 "Jail" (监狱)。
# 忽略的 IP 地址,这些 IP 永远不会被封禁。# 127.0.0.1/8 是本机回环地址,::1 是 IPv6 的本机回环地址。建议将您自己的固定 IP 也加入此列表。ignoreip = 127.0.0.1/8 ::1 你的可信ip_1 你的可信ip_2
# 默认封禁时长。单位可以是 s(秒), m(分钟), h(小时), d(天), w(周)。这里是 1 天。bantime = 1d
# 查找时间窗口。Fail2ban 会在此时间段内统计客户端的失败次数。这里是 10 分钟。findtime = 10m
# 最大重试次数。在 `findtime` 时间窗口内,如果失败次数达到此值,客户端 IP 将被封禁。这里是 5 次。# 结合上面的 findtime,意味着“10分钟内失败5次”。maxretry = 5
# 触发封禁时执行的动作。%(action_)s 是一个变量,通常指向默认的封禁动作(如 iptables-multiport)。action = %(action_)s
# 对于 Debian 或 Ubuntu 并且你希望它和 UFW 集成 请删除 banaction = ufw 的注释# banaction = ufw
# =================================================================================# JAILS (监狱) - 职责明确,策略清晰# 每个 [section] 都是一个独立的 "监狱",用于监控一种特定的服务或攻击行为。# =================================================================================
# --- 基础安全 (SSH) ---[sshd]# 是否启用此监狱。true 为启用,false 为禁用。enabled = true# SSH 服务的端口号。 【重要】请务必修改为您服务器上实际的 SSH 端口!port = 22# 覆盖默认的 maxretry。SSH 是核心服务,策略更严格,3次失败就封禁。maxretry = 3# 覆盖默认的 bantime。对于攻击 SSH 的 IP,封禁更长时间,这里是 1 周。bantime = 1w
# --- Nginx 核心防护:恶意扫描器 ---# 监控并阻止常见的目录扫描、漏洞扫描工具。[nginx-pro-scanner]enabled = true# 监控的端口,http (80) 和 https (443)。port = http,https# 使用的过滤器规则文件名 (位于 /etc/fail2ban/filter.d/nginx-pro-scanner.conf)。【注意】此为自定义过滤器。filter = nginx-pro-scanner# 监控的 Nginx 日志文件路径。【重要】此路径通常用于宝塔面板,请根据您的实际情况修改。logpath = /www/wwwlogs/*.log
# --- Nginx 核心防护:恶意机器人与脚本 ---# 监控并阻止已知的恶意 User-Agent 或爬虫。[nginx-badbots]enabled = trueport = http,https# 使用的过滤器规则文件名 (位于 /etc/fail2ban/filter.d/nginx-badbots.conf)。【注意】此为自定义过滤器。filter = nginx-badbotslogpath = /www/wwwlogs/*.log# 策略非常严格,只要匹配到 1 次就封禁。maxretry = 1# 时间窗口缩短到 1 分钟,反应更迅速。findtime = 1m# 封禁 1 周。bantime = 1w
# --- Nginx 核心防护:SQL注入 & XSS 攻击尝试 ---# 监控 URL 或请求体中包含的典型 SQLi 和 XSS 攻击代码。[nginx-sqli-xss]enabled = trueport = http,https# 使用的过滤器规则文件名 (位于 /etc/fail2ban/filter.d/nginx-sqli-xss.conf)。【注意】此为自定义过滤器。filter = nginx-sqli-xsslogpath = /www/wwwlogs/*.log# 策略严格,5 分钟内尝试 2 次就封禁。maxretry = 2findtime = 5m# 封禁 1 周。bantime = 1w
# --- Nginx 辅助防护:畸形请求 (4xx 错误) ---# 监控产生大量 4xx 客户端错误(如 404 Not Found, 403 Forbidden)的 IP。[nginx-4xx-errors]enabled = trueport = http,https# 使用的过滤器规则文件名 (位于 /etc/fail2ban/filter.d/nginx-4xx-errors.conf)。【注意】此为自定义过滤器。filter = nginx-4xx-errorslogpath = /www/wwwlogs/*.log# 策略相对宽松,允许一定程度的错误,防止误封正常用户。5 分钟内 15 次 4xx 错误才封禁。maxretry = 15findtime = 5m# 封禁时间较短,6 小时,因为误封的可能性相对较高。bantime = 6h
# --- Nginx 辅助防护:HTTP Basic Auth 爆破 ---# 监控 Nginx 的 HTTP 基本认证失败日志。[nginx-http-auth]enabled = true# 【最终修正】为保证服务稳定启动,只监控最核心且确定存在的 nginx_error.log。# HTTP 认证失败通常记录在错误日志中,而不是访问日志。logpath = /www/wwwlogs/nginx_error.log# 3 次认证失败就封禁。maxretry = 3# 封禁 1 周。bantime = 1w
# --- 累犯加重处罚规则 (Recidive) ---# 这是一个特殊的“元监狱”,它不监控服务日志,而是监控 Fail2ban 自己的日志。# 用来惩罚那些在短时间内被多次封禁的“惯犯” IP。[recidive]enabled = true# 监控 Fail2ban 自己的日志文件。路径在各系统上可能不同,但 /var/log/fail2ban.log 是最常见的。logpath = /var/log/fail2ban.log# 执行更严厉的封禁动作,通常是封禁所有端口 (allports),而不仅仅是触发的那个端口。action = %(banaction_allports)s# 时间窗口为 1 天。findtime = 1d# 如果一个 IP 在 1 天内被其他任何监狱封禁了 3 次...maxretry = 3# ...那么它将被这个监狱处以更长的封禁时间:2 周,并且是所有端口。bantime = 2w
步骤 2.5: 创建一个全新的、更强大的 Nginx 过滤器
创建一个新文件 /etc/fail2ban/filter.d/nginx-pro-scanner.conf
,并将以下内容完整复制进去:
[Definition]# 匹配各种恶意扫描行为,状态码可以是 3xx, 4xxfailregex = ^<HOST> .* "(GET|POST) .*/\.(git|env|svn|htpasswd|sql|bak|conf|ini|rar|zip|tgz|gz|bz2)[^"]*" (30|40)\d .* ^<HOST> .* "(GET|POST) .*/(phpmyadmin|pma|admin|db|mysql|websql|backup|dump)[^"]*" (30|40)\d .* ^<HOST> .* "(GET|POST) .*/(wp-admin|wp-login|wp-content|wp-includes|wordpress|wp)[^"]*" (30|40)\d .* ^<HOST> .* "(GET|POST) /xmlrpc\.php" (30|40)\d .* ^<HOST> .* "(GET|POST) /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin\.php" (30|40)\d .* ^<HOST> .* "GET .*\?phpinfo=.*" .* ^<HOST> .* "GET .*/(console|invokefunction|api/jsonws/invoke)" .*
ignoreregex =
创建一个新文件 /etc/fail2ban/filter.d/nginx-badbots.conf
,并将以下内容完整复制进去:
[Definition]# User-Agent 黑名单,不区分大小写 (?i)# 包含常见扫描工具、脚本语言、某些过于激进的爬虫failregex = ^<HOST> .* "(?i).*(Go-http-client|AhrefsBot|SemrushBot|MegaIndex|BLEXBot|DotBot|Nmap|masscan|zgrab|sqlmap|nikto|python-requests|curl|wget|scan|spider|bot|crawler).*"$ ^<HOST> .* "-" "-"$
# 忽略主流搜索引擎爬虫,防止误伤ignoreregex = (?i).*(googlebot|bingbot|baidu|slurp|duckduckbot|applebot|yandex|facebookexternalhit)
创建一个新文件 /etc/fail2ban/filter.d/nginx-sqli-xss.conf
,并将以下内容完整复制进去:
[Definition]# 解码后的URL中包含SQL注入或XSS攻击的典型关键字# (?i) 不区分大小写,\s 代表空格failregex = ^<HOST> .* "(?i).*(union\s*select|select.*from|insert\s*into|<\s*script>|%%3Cscript%%3E|<\s*img|onmouseover|javascript:).*" .*
ignoreregex =
创建一个新文件 /etc/fail2ban/filter.d/nginx-4xx-errors.conf
,并将以下内容完整复制进去:
[Definition]# 捕获返回 4xx 客户端错误的请求,例如 400, 403, 404, 405 等failregex = ^<HOST> -.*- .* 4\d\d .*
# 忽略对 favicon.ico 和 robots.txt 的 404 请求,这些很常见ignoreregex = .*(GET|HEAD) /(favicon.ico|robots.txt) .*
3. 生效与验证
配置完成后,必须重启服务才能让新配置生效。
步骤 3.1: 重启 Fail2ban 服务
# 重启服务以加载 jail.local 中的新配置sudo systemctl restart fail2ban
步骤 3.2: 验证规则是否加载成功
使用 fail2ban-client
工具检查所有规则(Jail)是否已成功加载并运行。
# 查看 Fail2ban 整体状态sudo fail2ban-client status
成功标志:在输出的
Jail list
中,能看到您在jail.local
里启用了enabled = true
的所有规则名称,例如sshd
,nginx-bad-requests
等。常见问题:如果发现某个自定义的 Jail (如
nginx-bad-requests
) 没有出现在列表中,通常是因为缺少filter
定义。请返回jail.local
文件,在该 Jail 段落中添加一行filter = nginx-botsearch
。
4. 日常管理与维护
4.1 查看封禁状态
查看特定规则的封禁IP(最常用)
# 查看 SSH 服务的封禁列表sudo fail2ban-client status sshd
# 查看核心漏洞扫描(最常用)sudo fail2ban-client status nginx-pro-scanner
# 查看恶意机器人封禁列表sudo fail2ban-client status nginx-badbots
# 看 SQL 注入 / XSS 攻击尝试sudo fail2ban-client status nginx-sqli-xss
# 看“骚扰型”扫描sudo fail2ban-client status nginx-4xx-errors
关键信息:在输出结果中查找
Banned IP list
,后面就是被封禁的IP地址。
查看所有规则的封禁IP(概览)
# 使用一行命令遍历并显示所有已启用规则的状态sudo fail2ban-client status | grep "Jail list:" | sed -e 's/.*Jail list:[ \t]*//' -e 's/,//g' | xargs -n1 sudo fail2ban-client status
4.2 手动解封 IP
如果您需要解封某个IP(例如误封了自己或合作伙伴的IP)。
# 命令格式: sudo fail2ban-client set <规则名> unbanip <要解封的IP>
# 示例:解封被 sshd 规则封禁的IP 123.123.123.123sudo fail2ban-client set sshd unbanip 123.123.123.123
4.3 紧急情况处理:解救被锁在外的自己
如果您不慎被封禁,无法通过SSH登录,请按以下步骤操作。
- 通过服务商后台登录:使用云服务商提供的 VNC 控制台 或 网页版紧急终端 登录服务器。这是您的“救命稻草”,可以绕过网络防火墙。
- 执行解封命令:在VNC控制台中,执行
4.2
中的解封命令。 - 终极手段:如果解封命令不奏效,可以临时停止Fail2ban服务。服务停止时,它会自动移除所有防火墙封禁规则。
成功通过SSH登录后,别忘了回来把服务重新启动:
Terminal window # 临时停止服务,所有封禁会立即解除sudo systemctl stop fail2banTerminal window sudo systemctl start fail2ban
5. 核心概念回顾
- 工作原理:监控日志 -> 匹配模式 -> 执行动作 (Ban)。
- 封禁机制:Fail2ban 自身不拦截流量,而是通过调用系统防火墙 (firewalld/iptables) 来添加/删除规则以实现IP的封禁和解封。
- 封禁记录位置:实时记录在内存中,历史记录在
/var/lib/fail2ban/fail2ban.sqlite3
数据库中,实际拦截规则在防火墙中。 - 黄金法则:永远只修改
jail.local
文件,保持jail.conf
的原始状态。
6. 常见问题与故障排查 (Troubleshooting)
本章节记录了在使用 Fail2ban 过程中可能遇到的常见问题及其解决方案。
问题一:修改配置并重启后,Fail2ban 启动失败
症状 (Symptom)
在你修改了任何 .conf
或 .local
文件并执行 sudo systemctl restart fail2ban
后,所有 fail2ban-client
命令都返回错误:
ERROR Failed to access socket path: /var/run/fail2ban/fail2ban.sock. Is fail2ban running?
这表明 Fail2ban 主服务在启动过程中遇到了致命错误,导致启动失败。
诊断 (Diagnosis)
要找出根本原因,我们需要查看 Fail2ban 的详细启动日志。执行以下命令:
sudo journalctl -xeu fail2ban
请重点关注日志末尾的红色错误信息。最常见的一个错误是:
ERROR Failed during configuration: Have not found any log file for recidive jail
错误原因:这个错误意味着 [recidive]
监狱需要监控的日志文件 /var/log/fail2ban.log
不存在。在很多系统的默认安装中,这个文件并不会被自动创建。当 Fail2ban 严格重启并加载配置时,找不到这个依赖文件,就会导致整个服务启动失败。
解决方案 (Solution)
我们只需要手动创建这个空的日志文件,然后再次重启服务即可。
# 步骤 1: 手动创建空的日志文件sudo touch /var/log/fail2ban.log
# 步骤 2: 再次重启 Fail2ban 服务sudo systemctl restart fail2ban
最佳实践:为了从根源上避免此问题,建议在任何新服务器上安装完 Fail2ban 后,立即执行 sudo touch /var/log/fail2ban.log
作为初始化步骤的一部分。
7. 高级应用案例:豁免特定应用流量 (如 X-UI 面板)
场景 (Scenario)
我们强大而严格的 [nginx-badbots]
规则,可能会“误伤”一些行为类似脚本的正常应用。例如,X-UI 面板的 VLESS 等协议,其客户端的 User-Agent 可能是 Go-http-client
,这会被我们的规则识别为恶意机器人并立即封禁。
当你的 IP 地址是动态变化的,使用 ignoreip
白名单不再可行。此时,我们需要创建一条精准的豁免规则。
解决方案:通过 ignoreregex
豁免特定 URL 路径
我们的策略是:不降低整体安全性,仅为这些特殊应用的合法流量打开一个“特殊通道”。
操作步骤:
- 编辑
nginx-badbots
过滤器文件:Terminal window sudo nano /etc/fail2ban/filter.d/nginx-badbots.conf - 找到
ignoreregex
这一行,并在末尾添加对你特定路径的豁免。
案例 A: 豁免单个路径
如果你的 VLESS 流量都通过 /bwgx
这个路径,你需要将 ignoreregex
修改为:
# 注意末尾用 | 分隔,并添加了 GET /your_path HTTP 的模式ignoreregex = (?i).*(googlebot|bingbot|baidu|slurp|duckduckbot|applebot|yandex|facebookexternalhit)|GET /bwgx HTTP
这行规则的意思是:忽略主流搜索引擎,或者忽略所有访问 /bwgx
路径的请求。
案例 B: 豁免多个路径
如果你有多个路径需要豁免,例如 /bwgx
, /bwgv
, 和 /wyf
,你需要使用 ()
进行分组,并用 |
分隔:
# 使用 (path1|path2|...) 的格式来豁免多个路径ignoreregex = (?i).*(googlebot|bingbot|baidu|slurp|duckduckbot|applebot|yandex|facebookexternalhit)|GET /(bwgx|bwgv|bwgo) HTTP
这个 (bwgx|bwgv|bwgo)
正则表达式会匹配这三个路径中的任意一个。
最后一步:修改完过滤器后,务必重启 Fail2ban 以使新规则生效。
sudo systemctl restart fail2ban