nginx+Fail2Ban实现动态封禁IP
一、安装fail2ban
1、启用 EPEL 仓库(推荐)
fail2ban 包含在 EPEL(Extra Packages for Enterprise Linux)仓库中,您需要先启用它:
# 1. 安装 EPEL 仓库
sudo yum install -y epel-release
# 2. 更新仓库缓存
sudo yum makecache fast
# 3. 安装 fail2ban
sudo yum install -y fail2ban
2、如果 EPEL 安装失败,可以手动配置
# 使用阿里云镜像安装 EPEL
sudo yum install -y https://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
# 然后安装 fail2ban
sudo yum install -y fail2ban
3、源码安装
# 安装依赖
sudo yum install -y python3 python3-pip git iptables
# 克隆 fail2ban 仓库
git clone https://github.com/fail2ban/fail2ban.git
cd fail2ban
# 安装
sudo python3 setup.py install
# 复制配置文件
sudo cp config/jail.conf /etc/fail2ban/jail.local
二、添加配置文件
安装后的默认路径:/etc/fail2ban
1、Filter
定义什么行为算违规?
vim /etc/fail2ban/filter.d/nginx-black.conf
[Definition]
#匹配所有请求
#failregex = "remote_ip":\s*"<HOST>".*"request":\s*"[^\"]+".*"response":\s*"[2345]\d\d"
#匹配/api/sms/code这个的所有请求
failregex = <HOST>.*"/api/sms/code
ignoreregex =
| 部分 | 含义 | 示例匹配 |
|---|---|---|
| ^ | 匹配行首 | - |
| Fail2Ban 特殊标记,自动匹配 IP 地址 | 192.168.1.100 | |
| \s+ | 匹配 1 个或多个空白字符(空格、制表符等) | |
| .* | 匹配任意字符 0 多次 | - - [30/Mar/2025:10:30:15 +0800] |
| " | 匹配字面的双引号 | " |
| (GET|POST) | 匹配 GET 或 POST 方法 | GET 或 POST |
| \s+ | 匹配字面的双引号 | " |
| /api/platform/staff/register/ | 匹配固定的 API 路径前缀 | /api/platform/staff/register/ |
| .* | 匹配任意后续路径 | ?username=test 或 /verify 等 |
| \s+ | 匹配 1 个或多个空白字符 | |
| HTTP/[0-9.]+ | 匹配 HTTP 协议版本 | HTTP/1.1、HTTP/2.0 |
| " | 匹配结束的双引号 | " |
| \s+ | 匹配 1 个或多个空白字符 | |
| 200 | 只匹配 HTTP 状态码 200(请求成功) | 200 |
| \s | 匹配最后的空白字符(后面通常是响应字节数) |
ignoreregex 忽略正则表达式
- 空值表示不忽略任何匹配的日志
- 如果某些正常请求也需要访问这个接口,可以在此添加排除规则 会匹配的日志
192.168.1.100 - - [30/Mar/2025:10:30:15 +0800] "GET /api/platform/staff/register/verify HTTP/1.1" 200 1234 "-" "Mozilla/5.0"
10.0.0.55 - - [30/Mar/2025:10:31:20 +0800] "POST /api/platform/staff/register?token=abc123 HTTP/1.1" 200 567 "-" "curl/7.68.0"
不会匹配的日志
# 状态码不是 200
192.168.1.100 - - [...] "GET /api/platform/staff/register HTTP/1.1" 404 123 "-" "..."
#路径不匹配:
192.168.1.100 - - [...] "GET /api/platform/staff/register HTTP/1.1" 404 123 "-" "..."
#其他请求方法(如 PUT、DELETE):
192.168.1.100 - - [...] "DELETE /api/platform/staff/register HTTP/1.1" 200 0 "-" "..."
2、action
"违规后怎么处理?"
sudo vim /etc/fail2ban/filter.d/nginx-black-action.conf
[Definition]
actionstart = docker exec nginx nginx -s reload
actionstop =
actioncheck =
actionban = echo "deny <ip>;" >> /usr/local/nginx/blockedips.conf && docker exec nginx nginx -s reload
actionunban = sed -i "/deny <ip>;/d" /usr/local/nginx/blockedips.conf && docker exec nginx nginx -s reload
3、jail.local
用于定义"监控策略"和"处置规则" 创建配置文件
- fail2ban 启动时先读取 /etc/fail2ban/jail.conf(默认配置,只读参考)
- 然后尝试读取 /etc/fail2ban/jail.local(用户自定义配置)
- 如果 jail.local 存在,会覆盖 jail.conf 中的相同配置项
- 如果 jail.local 不存在,只使用 jail.conf 的默认配置
jail.local不存在的时候,可以使用下面的方式来创建
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
[nginx-black]
enabled = true
port = http,https
filter = nginx-black
action = nginx-black-action
logpath = /usr/local/nginx/logs/access.log
# 5 次就封禁
maxretry = 5
# 封禁时长(秒)= 3600*24 *7 小时
bantime = 30
# 检测时间窗口(秒)= 30 s
findtime = 60
- 在这个的最后面增加后面的的配置
- nginx-black为filter的文件名字
- nginx-black-action为action的文件名字
- logpath是定义需要监控的文件名字
四、与nginx联动
1、http中配置
http {
include /usr/local/nginx/blockedips.conf;
....其他的配置(直接放在第一行)
2、server(限制整个server)
server {
include /usr/local/nginx/blockedips.conf;
....其他的配置(直接放在第一行)
2、server(限制整个server)
server {
listen 80;
server_name localhost;
# 只对 API 接口进行 IP 封禁
location /api/ {
include /usr/local/nginx/blockedips.conf;
....其他的配置(直接放在location后配置的第一行)
五、基本命令
# 启动 fail2ban
sudo systemctl start fail2ban
# 设置开机自启
sudo systemctl enable fail2ban
# 查看状态
sudo systemctl status fail2ban
# 查看 jail 列表
sudo fail2ban-client status
# 验证nginx-black匹配的结果
sudo fail2ban-regex /usr/local/nginx/logs/access.log /etc/fail2ban/filter.d/nginx-black.conf
# 查看nginx-black的状态
sudo fail2ban-client status nginx-black
# 查看nginx-black中的maxretry配置
sudo fail2ban-client get nginx-black maxretry
# 查看nginx-black中的findtime配置
sudo fail2ban-client get nginx-black findtime
# 查看nginx-black中的bantime配置
sudo fail2ban-client get nginx-black bantime
# 查看nginx-black中的封禁IP
sudo fail2ban-client get nginx-black banned
#查看fail2ban的日志
tail -n 50 /var/log/fail2ban.log