fail2ban 是一个开源的入侵防护工具,通过实时监控日志文件,根据预定义的规则自动识别恶意行为,并调用防火墙(firewalld / iptables)封禁来源 IP。

一、fail2ban 是什么
-
实时监控日志,无需定时任务。
-
支持正则匹配,灵活定义“恶意行为”。
-
自动调用系统防火墙封禁 / 解封。
-
支持设置封禁时长,到期自动解封。
-
支持递增封禁(repeat offenders)。
-
支持邮件通知(可选)。
二、安装
dnf install -y epel-release
dnf install -y fail2ban
验证安装:
fail2ban-client --version
三、目录结构
/etc/fail2ban/
├── fail2ban.conf # 主配置(一般不改)
├── jail.conf # 默认规则(不要直接改,升级会覆盖)
├── jail.local # 自定义规则(写在这里)
├── jail.d/ # 额外 jail 配置目录
├── filter.d/ # 过滤器目录(定义匹配规则)
│ └── apache-scan.conf # 你自己写的精准扫描过滤器
├── action.d/ # 动作目录(定义封禁方式)
└── firewallcmd-rich-rules.conf # 调用 firewalld
核心原则:不要改
jail.conf和filter.d/下的默认文件,自定义内容写到jail.local和新建的 filter 文件中,升级不会被覆盖。
四、核心概念
4.1 Jail(监狱)
一条防护规则,定义了监控哪个日志、用什么过滤器、匹配多少次后封禁、封禁多久。
4.2 Filter(过滤器)
定义正则表达式,从日志中提取恶意行为的特征行。
4.3 Action(动作)
定义封禁方式,比如调用 firewalld、iptables、发送邮件等。
4.4 工作流程
日志文件 → Filter(正则匹配)→ 达到阈值 → Action(封禁 IP)→ 到期自动解封
4.5 关键参数
| 参数 | 含义 | 示例 |
enabled |
是否启用 | true / false |
port |
监控的端口 | http,https |
filter |
使用的过滤器名称 | apache-scan |
logpath |
监控的日志文件路径 | /Data/.../access.log |
maxretry |
触发封禁的匹配次数 | 30 |
findtime |
统计次数的时间窗口(秒) | 60 |
bantime |
封禁持续时间(秒),-1 为永久 | 86400(24小时) |
banaction |
封禁使用的动作 | firewallcmd-rich-rules |
五、实战配置
5.1 创建过滤器:精准扫描行为检测(access.log)
创建 /etc/fail2ban/filter.d/apache-scan.conf,写入以下精细化规则:
cat > /etc/fail2ban/filter.d/apache-scan.conf << 'EOF'
[Definition]
failregex = ^<HOST> -.*"(GET|POST|HEAD).*/(\.env|env\.)".*$
^<HOST> -.*"(GET|POST|HEAD).*/(\.git(/|config)|\.gitlab-ci\.yml|\.github|\.idea|\.vscode).*".*$
^<HOST> -.*"(GET|POST|HEAD).*/(amplify\.yml|firebase\.json|vite\.config|nuxt\.config|next\.config|Jenkinsfile|\.pypirc|composer\.json).*".*$
^<HOST> -.*"(GET|POST|HEAD).*/(db|database)\.sql.*".*$
^<HOST> -.*"(GET|POST|HEAD).*/(storage/logs|var/log|config)/.*".*$
^<HOST> -.*"(GET|POST|HEAD).*/goform/.*".*$
^<HOST> -.*"(GET|POST|HEAD).*/(wp-admin|wp-login|xmlrpc\.php|wp-json|wp-content|wp-includes|actuator|phpmyadmin|ueditor|graphql).*".*$
^<HOST> -.*"(GET|POST|HEAD).*/(id_rsa|id_dsa|config\.js|\.cgi|\.key|\.pem|\.bak|\.sql|\.sh|\.tar.gz|\.conf|\.config|\.log|\.alfa|\.yaml|\.yml|\.cc|\.asp|\.ashx|\.aspx|\.jsp|\.py|\.axd|\.do|shell|webshell).*".*$
^<HOST> -.*"(GET|POST|HEAD).*(%%5c|%%5C|\\|%%2e%%2e|\.\/).*$"
^<HOST> -.*"(GET|POST|HEAD).*/(etc/passwd|@fs/|@vite/|__).*".*$
ignoreregex =
EOF
5.2 验证过滤器能否匹配日志
fail2ban-regex /Data/Public_Root/iewb.net/logs/access.log /etc/fail2ban/filter.d/apache-scan.conf
5.3 创建 jail.local 配置(整合三个监狱)
创建 /etc/fail2ban/jail.local:
cat > /etc/fail2ban/jail.local << 'EOF'
[DEFAULT]
# 封禁动作:使用 firewalld rich rules
banaction = firewallcmd-rich-rules
# 封禁时间:24小时(秒)
bantime = 86400
# 统计时间窗口:60秒内
findtime = 60
# 忽略本机和指定IP(多个用空格分隔)
ignoreip = 127.0.0.1/8
# ============ 1. 自定义精准扫描行为防护 ============
[apache-scan]
enabled = true
port = http,https
filter = apache-scan
logpath = /Data/Public_Root/iewb.net/logs/access.log
maxretry = 5
findtime = 60
bantime = 86400
# ============ 2. 恶意爬虫与采集器拦截 ============
[apache-badbots]
enabled = true
port = http,https
filter = apache-badbots
logpath = /Data/Public_Root/iewb.net/logs/access.log
maxretry = 2
findtime = 60
bantime = 86400
# ============ 3. 盲目路径乱扫防御 ============
[apache-nohome]
enabled = true
port = http,https
filter = apache-nohome
logpath = /Data/Public_Root/iewb.net/logs/access.log
maxretry = 5
findtime = 60
bantime = 86400
EOF
核心监狱(Jail)作用介绍:
-
[apache-scan](自定义精准扫描防御):监控访问日志,专门打击各类自动化扫描器对.env敏感配置、.git版本控制目录、数据库备份、漏洞路径以及目录遍历字符(../等)的恶意探测。 -
[apache-badbots](恶意爬虫与采集器拦截):自动识别并拦截互联网上已知的垃圾流量采集器、恶意的 User-Agent 和非法的网络爬虫,减少服务器带宽浪费并保护内容资产。 -
[apache-nohome](盲目路径乱扫防御):针对盲目请求网站中根本不存在的用户主目录或诡异随机路径的异常行为进行监控,一经高频触发即刻拉黑。
5.4 启动与开机自启
systemctl enable --now fail2ban
六、常用管理命令
6.1 查看状态
# 查看所有 jail 列表
fail2ban-client status
# 查看某个 jail 详情(含封禁 IP 数量和列表)
fail2ban-client status apache-scan
fail2ban-client status apache-badbots
fail2ban-client status apache-nohome
# 只看被封禁的 IP
fail2ban-client status apache-scan | grep "Banned IP"
6.2 手动封禁 / 解封
# 手动封禁
fail2ban-client set apache-scan banip 1.2.3.4
# 手动解封
fail2ban-client set apache-scan unbanip 1.2.3.4
6.3 查看日志
# 实时跟踪
tail -f /var/log/fail2ban.log
# 查看今天的封禁记录
grep "Ban" /var/log/fail2ban.log | grep "$(date +%Y-%m-%d)"
6.4 重载配置
# 修改 jail.local 或过滤器后重载
fail2ban-client reload
七、进阶用法
7.1 修改封禁时间
# 临时修改为永久封禁
fail2ban-client set apache-scan bantime -1
# 临时修改为 1 小时
fail2ban-client set apache-scan bantime 3600
7.2 查看 firewalld 中 fail2ban 添加的规则
firewall-cmd --list-rich-rules | grep fail2ban
八、故障排查
# 测试过滤器是否能匹配日志
fail2ban-regex /Data/Public_Root/iewb.net/logs/access.log /etc/fail2ban/filter.d/apache-scan.conf
# 检查配置语法
fail2ban-client --test
# 查看详细运行日志
journalctl -u fail2ban -f
九、速查表
| 项目 | 说明 |
| 配置文件 | /etc/fail2ban/jail.local |
| 过滤器目录 | /etc/fail2ban/filter.d/*.conf |
| 日志文件 | /var/log/fail2ban.log |
| 启动服务 | systemctl enable --now fail2ban |
| 查看状态 | fail2ban-client status apache-scan |
| 查看封禁 IP | fail2ban-client status apache-scan | grep "Banned IP" |
| 解封 IP | fail2ban-client set apache-scan unbanip x.x.x.x |
| 重载配置 | fail2ban-client reload |