如何在Nginx中实现动态请求过滤规则
想要在 Nginx 中实现动态请求过滤规则(如封禁 IP、拦截路径、限制请求方法 / 频率等),核心思路是「配置解耦 + 热加载 + 动态推送」—— 将过滤规则从 Nginx 主配置中分离,通过外部配置文件 / 配置中心管理规则,修改后无需重启 Nginx,仅需热加载即可生效。以下是 4 种主流实现方案,从简单到进阶,覆盖单体、集群、高并发场景。
核心原理
Nginx 实现动态过滤的关键是:
- 规则解耦:将可变的过滤规则(如封禁 IP、拦截路径)写入独立配置文件,主配置通过
include引入; - 热加载:使用
nginx -s reload加载新配置,不中断现有连接; - 动态更新:通过脚本 / 配置中心修改独立配置文件,实现规则实时推送。
方案 1:基础方案(独立配置文件 + 手动热加载)
适合小型应用 / 测试环境,手动修改规则文件并热加载,实现简单、无额外依赖。
步骤 1:拆分 Nginx 配置
将过滤规则写入独立文件,主配置通过
include 引入:1.1 主配置(nginx.conf)
nginx
http {
# 引入动态规则文件(IP封禁、路径拦截)
include /etc/nginx/conf.d/dynamic_filter/*.conf;
server {
listen 80;
server_name localhost;
# ========== 1. IP封禁规则 ==========
if ($blocked_ip) {
return 403 "IP已被封禁";
}
# ========== 2. 路径拦截规则 ==========
if ($blocked_path) {
return 503 "接口临时维护";
}
# ========== 3. 请求方法限制 ==========
if ($disallowed_method) {
return 405 "不支持的请求方法";
}
# 正常转发请求到后端服务
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
1.2 动态规则文件(/etc/nginx/conf.d/dynamic_filter/block_rules.conf)
nginx
# 1. IP封禁规则(map 指令:匹配客户端IP,返回1则封禁)
map $remote_addr $blocked_ip {
default 0; # 默认不封禁
192.168.1.100 1; # 封禁IP 192.168.1.100
10.0.0.5 1; # 封禁IP 10.0.0.5
}
# 2. 路径拦截规则(map 指令:匹配请求路径,返回1则拦截)
map $request_uri $blocked_path {
default 0;
/api/test 1; # 拦截路径 /api/test
/admin 1; # 拦截路径 /admin
}
# 3. 请求方法限制(仅允许 GET/POST)
map $request_method $disallowed_method {
default 1; # 默认拦截
GET 0; # 放行 GET
POST 0; # 放行 POST
}
步骤 2:动态更新规则 + 热加载
2.1 修改规则文件(如新增封禁 IP)
bash
运行
# 编辑 block_rules.conf,添加新IP
echo "map \$remote_addr \$blocked_ip {
default 0;
192.168.1.100 1;
10.0.0.5 1;
172.16.0.8 1; # 新增封禁IP
}" > /etc/nginx/conf.d/dynamic_filter/block_rules.conf
2.2 热加载 Nginx 配置(无需重启,不中断服务)
bash
运行
nginx -s reload
验证效果
bash
运行
# 访问被封禁IP的接口,返回403
curl -x 127.0.0.1:80 http://localhost/api/test -H "X-Real-IP: 192.168.1.100"
# 返回:IP已被封禁(状态码403)
# 用 PUT 方法访问,返回405
curl -X PUT http://localhost/api/test
# 返回:不支持的请求方法(状态码405)
优缺点
- ✅ 优点:实现简单、无额外依赖、热加载不中断服务;
- ❌ 缺点:手动操作、不适合集群环境、规则变更需登录服务器。
方案 2:进阶方案(脚本 + 定时拉取配置中心)
适合中小型集群,通过脚本定时从配置中心(如 Nacos/Apollo)拉取规则,自动更新配置文件并热加载,实现规则「半自动化」推送。
步骤 1:配置中心存储规则(以 Nacos 为例)
在 Nacos 中创建配置:
- Data ID:
nginx_block_rules.conf - Group:
DEFAULT_GROUP - 配置内容(与方案 1 的 block_rules.conf 一致):
nginx
map $remote_addr $blocked_ip {
default 0;
192.168.1.100 1;
}
map $request_uri $blocked_path {
default 0;
/api/test 1;
}
步骤 2:编写拉取规则的 Shell 脚本
创建
update_nginx_rules.sh,定时拉取 Nacos 配置并更新:bash
运行
#!/bin/bash
# 配置中心地址
NACOS_URL="http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nginx_block_rules.conf&group=DEFAULT_GROUP"
# Nginx 规则文件路径
RULE_FILE="/etc/nginx/conf.d/dynamic_filter/block_rules.conf"
# 临时文件
TMP_FILE="/tmp/nginx_block_rules.tmp"
# 1. 从 Nacos 拉取最新规则
curl -s $NACOS_URL -o $TMP_FILE
# 2. 对比规则是否变更(避免重复热加载)
if ! diff $TMP_FILE $RULE_FILE > /dev/null; then
# 3. 更新规则文件
cp $TMP_FILE $RULE_FILE
# 4. 验证 Nginx 配置语法
nginx -t
if [ $? -eq 0 ]; then
# 5. 语法正确,热加载配置
nginx -s reload
echo "$(date):规则更新并热加载成功" >> /var/log/nginx/rule_update.log
else
echo "$(date):配置语法错误,放弃热加载" >> /var/log/nginx/rule_update.log
fi
fi
# 6. 删除临时文件
rm -f $TMP_FILE
步骤 3:设置定时任务(crontab)
定时执行脚本,拉取最新规则(如每 10 秒执行一次):
bash
运行
# 编辑 crontab
crontab -e
# 添加定时任务(每10秒执行)
*/10 * * * * /bin/bash /usr/local/bin/update_nginx_rules.sh
优缺点
- ✅ 优点:规则集中管理、自动化更新、适配集群(所有 Nginx 节点拉取同一配置);
- ❌ 缺点:规则生效有延迟(取决于定时频率)、仅支持静态规则(无法基于请求参数动态过滤)。
方案 3:高级方案(OpenResty + Lua + 配置中心)
适合高并发 / 复杂场景,基于 OpenResty(Nginx + Lua)实现「实时规则推送 + 动态过滤」,支持复杂逻辑(如请求参数过滤、限流)。
前置准备
安装 OpenResty(集成 Lua 解释器的 Nginx):
bash
运行
# CentOS
yum install openresty -y
# Ubuntu
apt install openresty -y
步骤 1:Nginx 配置(集成 Lua 脚本)
nginx
http {
# 加载 Lua 模块
lua_package_path "/usr/local/openresty/lualib/?.lua;;";
lua_package_cpath "/usr/local/openresty/lualib/?.so;;";
server {
listen 80;
server_name localhost;
# 每个请求执行 Lua 过滤脚本
access_by_lua_block {
-- 1. 引入自定义过滤脚本
local filter = require("dynamic_filter")
-- 2. 执行过滤逻辑(返回 true 则拦截)
local blocked = filter.check_rules(ngx.var.remote_addr, ngx.var.request_uri, ngx.var.request_method)
if blocked then
ngx.status = 403
ngx.say("请求被拦截")
ngx.exit(403)
end
}
# 转发请求到后端
location / {
proxy_pass http://127.0.0.1:8080;
}
}
}
步骤 2:Lua 过滤脚本(动态拉取规则)
创建
/usr/local/openresty/lualib/dynamic_filter.lua,从 Redis/Nacos 实时拉取规则:lua
local redis = require "resty.redis"
-- 检查过滤规则
function _M.check_rules(client_ip, request_uri, request_method)
-- 1. 连接 Redis(存储动态规则)
local red = redis:new()
red:set_timeout(1000) -- 1秒超时
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.log(ngx.ERR, "Redis 连接失败:", err)
return false -- 连接失败时放行
end
-- 2. 从 Redis 获取封禁IP列表
local blocked_ips = red:smembers("nginx:blocked_ips")
for _, ip in ipairs(blocked_ips) do
if client_ip == ip then
red:close()
return true -- IP 封禁,拦截请求
end
end
-- 3. 从 Redis 获取拦截路径列表
local blocked_paths = red:smembers("nginx:blocked_paths")
for _, path in ipairs(blocked_paths) do
if request_uri == path then
red:close()
return true -- 路径拦截
end
end
-- 4. 关闭 Redis 连接
red:close()
return false -- 规则通过,放行
end
return _M
步骤 3:动态更新 Redis 规则(实时生效)
通过 Redis 命令 / 接口更新规则,无需重启 / 热加载 Nginx(Lua 脚本每次请求都会拉取最新规则):
bash
运行
# 1. 封禁IP(添加到 Redis 集合)
redis-cli SADD nginx:blocked_ips 192.168.1.100
# 2. 拦截路径
redis-cli SADD nginx:blocked_paths /api/test
# 3. 解封IP
redis-cli SREM nginx:blocked_ips 192.168.1.100
优缺点
- ✅ 优点:规则实时生效(无延迟)、支持复杂过滤逻辑(参数 / 频率 / 地域)、高性能(Lua 原生执行);
- ❌ 缺点:需学习 Lua 语法、依赖 OpenResty/Redis、维护成本略高。
方案 4:企业级方案(Nginx + APISIX/OpenResty Dashboard)
适合大型集群,基于 APISIX(云原生网关,基于 OpenResty)实现可视化规则管理,支持「一键推送规则 + 灰度发布 + 监控告警」。
核心步骤
- 部署 APISIX:替代原生 Nginx,提供可视化控制台;
- 配置过滤规则:在控制台添加「IP 黑名单」「路径拦截」「请求方法限制」等规则;
- 动态推送规则:规则修改后自动同步到所有 APISIX 节点,实时生效;
- 监控告警:查看拦截日志、请求频率,配置规则变更告警。
示例:APISIX 配置 IP 黑名单
yaml
# apisix/config.yaml
routes:
- id: 1
uri: /*
upstream:
nodes:
"127.0.0.1:8080": 1
plugins:
ip-restriction:
blacklist:
- 192.168.1.100
- 10.0.0.5
修改后通过 APISIX 接口推送:
bash
运行
curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-d '{
"uri": "/*",
"upstream": {"nodes": {"127.0.0.1:8080": 1}},
"plugins": {
"ip-restriction": {"blacklist": ["192.168.1.100", "10.0.0.5", "172.16.0.8"]}
}
}'
优缺点
- ✅ 优点:可视化管理、集群自动同步、支持灰度发布 / 监控 / 告警、功能丰富(限流 / 熔断 / 缓存);
- ❌ 缺点:部署复杂度高、需额外资源(APISIX 集群)。
关键注意事项
1. 性能优化
- 缓存规则:方案 3 中,Lua 脚本可缓存 Redis 规则(如设置 10 秒缓存),减少 Redis 压力;
- 规则分片:集群环境下,将规则按地域 / 业务分片,避免单节点规则过大;
- 语法检查:热加载前执行
nginx -t验证配置,避免语法错误导致 Nginx 无法启动。
2. 规则持久化
- 配置中心 / Redis 中的规则需持久化(如 Redis 开启 RDB/AOF),避免重启丢失;
- 规则变更记录日志,便于追溯和回滚。
3. 安全防护
- 限制配置文件 / 脚本的访问权限(如
chmod 600 block_rules.conf),防止恶意修改; - 配置中心 / Redis 需设置密码,避免规则被篡改。
总结
Nginx 实现动态请求过滤规则的核心方案:
表格
| 方案 | 实现方式 | 生效延迟 | 适用场景 | 核心优势 |
|---|---|---|---|---|
| 独立配置文件 + 热加载 | 手动修改文件 + nginx reload | 秒级 | 小型应用 / 测试环境 | 简单、无依赖 |
| 脚本 + 配置中心 | 定时拉取 + 自动热加载 | 定时频率(如 10 秒) | 中小型集群 | 规则集中管理、自动化 |
| OpenResty + Lua + Redis | 实时拉取规则 | 实时 | 高并发 / 复杂逻辑场景 | 无延迟、支持复杂过滤 |
| APISIX 可视化管理 | 控制台推送 + 集群同步 | 实时 | 大型企业集群 | 可视化、易维护、功能丰富 |
选择建议:
- 小场景 / 快速实现:选方案 1;
- 中小型集群 / 自动化:选方案 2;
- 高并发 / 复杂逻辑:选方案 3;
- 企业级集群 / 可视化:选方案 4。
所有方案的核心都是「规则解耦 + 热加载 / 实时拉取」,确保规则变更无需重启 Nginx,不中断业务。
阅读剩余
版权声明:
作者:SE_Yang
链接:https://www.cnesa.cn/10657.html
文章版权归作者所有,未经允许请勿转载。
THE END
阿里云ECS服务器 - 限时特惠活动
云服务器爆款直降90%
新客首单¥68起 | 人人可享99元套餐,续费同价 | u2a指定配置低至2.5折1年,立即选购享更多福利!
新客首单¥68起
人人可享99元套餐
弹性计费
7x24小时售后