什么是 Fail2ban?
Fail2ban 是一个入侵防御软件框架,用于保护服务器免受暴力破解和其他自动化攻击。它通过监控系统日志(如 /var/log/auth.log
, /var/log/nginx/error.log
等)来检测恶意行为,例如多次失败的登录尝试。一旦检测到异常,它会自动调用防火墙规则(如 iptables, nftables, firewalld 等)来封锁可疑的IP地址一段时间。
核心概念
Jail(监禁): 核心概念。一个“Jail”定义了一个应用场景,它指定了:
要监控什么日志 (logpath
)
用什么规则来检测恶意行为 (filter
)
检测到后执行什么动作 (action
)
封禁多长时间 (bantime
)
触发封禁的阈值 (maxretry
, findtime
)
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
用您喜欢的文本编辑器(如 nano
, vim
)打开 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
来交互和管理。
-
-
查看状态: 查看所有启用的 Jail 及其状态。
sudo fail2ban-client status
- 查看特定 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
- 手动封禁一个IP:
sudo fail2ban-client set <jail-name> banip <ip-address> # 示例 sudo fail2ban-client set sshd banip 202.54.1.1
- 手动解封一个IP:
sudo fail2ban-client set <jail-name> unbanip <ip-address> # 示例 sudo fail2ban-client set sshd unbanip 202.54.1.1
- 解封所有IP:
sudo fail2ban-client set <jail-name> unban --all
第三部分:高级配置与自定义
1. 自定义过滤器 (Filter)
有时默认的过滤器可能不匹配您的日志格式,您需要自定义。
例如,为自定义服务创建过滤器:
-
-
创建过滤器文件:
sudo nano /etc/fail2ban/filter.d/my-service.conf
-
编写规则。一个简单的示例:
[Definition] failregex = ^.*Failed login from <HOST>.*$ # 这是一个示例,请根据您的实际日志编写正则表达式 ignoreregex =
<HOST> 是一个关键标签,用于匹配IP地址。
- 在
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。
示例:封禁时发送邮件
-
确保系统安装了邮件工具(如
sendmail
)。 -
在
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 是一个“设置后就不用管”的强大安全工具,但初始配置需要细心:
-
安装 Fail2ban。
-
创建
jail.local
并配置全局[DEFAULT]
设置(尤其是ignoreip
!)。 -
启用 您需要的 Jail(如
[sshd]
)。 -
根据需要自定义 Filter 和 Action。
-
重启 Fail2ban 服务。
-
使用
fail2ban-client
命令进行管理和监控。 -
遇到问题时查看
/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
文件中。这段配置做了以下几件事:-
在
[DEFAULT]
部分设置了全局规则(如白名单IP、封禁时间等)。 -
创建了一个名为
[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-proto6
和iptables-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依靠过滤器文件中的正则表达式来识别日志中的恶意行为。我们需要为您的日志创建一个。
-
创建过滤器文件:
vim /etc/fail2ban/filter.d/nginx-bad-request.conf
- 写入过滤规则。根据日志样例,写一个通用且有效的规则,用于更精准的强化防护,它专门针对已知的、特定类型的攻击手法,误报率极低。
[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\.)
过滤器规则解释
这个配置专门针对以下几种恶意行为:
-
常见错误状态码:
(404|400|403|499)
– 封禁产生大量”未找到”、”错误请求”、”禁止访问”等错误的IP。 -
PHP文件探测:
\.php
– 攻击者常尝试访问不存在的php文件来探测漏洞。 -
ASP文件探测:
\.asp
– 针对Windows服务器的探测。 -
后台管理目录扫描:
\/wp-admin
和\/admin
– 尝试寻找网站后台入口。 -
敏感文件扫描:
\/\.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
总结与建议
-
不要修改默认的
jail.conf
:始终在jail.local
和/etc/fail2ban/filter.d/
目录下进行自定义配置。 -
核心是过滤器:上面的
failregex
是一个通用规则。要获得最佳效果,您最好提供一段真实的恶意访问日志样例,这样可以编写出更精确的过滤规则。 -
调试工具:
fail2ban-regex
命令是您调试过滤器的最好朋友,一定要善用它。 -
观察日志:配置完成后,可以实时查看Fail2ban的日志来观察封禁情况:
sudo tail -f /var/log/fail2ban.log
高级技巧:封禁特定User-Agent
从日志中可以看到一些爬虫(如
SemrushBot
,GPTBot
)。如果您想封禁这些特定的爬虫,可以创建另一个过滤器: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
最终建议
-
先测试再启用:使用
fail2ban-regex
命令充分测试您的过滤器,确保不会误封正常用户。 -
逐步调整:开始时可以设置较短的封禁时间(如1小时),观察效果后再调整。
-
监控日志:封禁后查看
/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段
-
-
-
-