Nginx 用 map 指令实现动态 IP 鉴权,通过 $remote_addr 映射 $ip_allowed 变量,在 http 块顶层定义白名单/CIDR,配合 if 或 auth_request 拦截请求,支持代理 IP 修正与多维校验。

用 map 指令实现 Nginx 的动态 IP 鉴权,核心是把 IP 地址映射成一个可判断的开关变量,再配合 if 或更稳妥的模块(如 auth_request)做放行或拦截。它不依赖 reload,适合白名单/黑名单频繁变动的场景。
在 http 块中定义 IP 映射关系
map 必须写在 http 块顶层,不能放在 server 或 location 里。用 $remote_addr 提取客户端真实 IP(注意:若前端有代理,需先配置 set_real_ip_from 和 real_ip_header):
- 定义一个布尔型变量,比如
$ip_allowed,默认为0(拒绝) - 显式列出允许的 IP 或 CIDR 段,值设为
1 - 支持多行、注释、空格缩进,但不支持正则匹配 IP 段(需用 CIDR 精确写法)
示例:
map $remote_addr $ip_allowed {
default 0;
192.168.1.100 1;
203.0.113.0/24 1;
2001:db8::1 1;
}
在 location 中触发鉴权逻辑
有两种常用方式,推荐后者:
-
简单场景用 if 判断:在目标 location 内写
if ($ip_allowed = 0) { return 403; }。注意不能在if块里写proxy_pass,否则会出错 - 生产环境推荐 auth_request:把 IP 校验交给后端服务,由它查 Redis 或数据库实时返回结果。Nginx 只负责转发和拦截,策略完全热更新
例如:
location /api/ {
auth_request /_ip_check;
proxy_pass http://backend;
}
location = /_ip_check {
internal;
proxy_pass https://auth-svc/ip-check;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Real-IP $remote_addr;
}
配合 GeoIP 或设备信息做增强判断
单一 IP 控制粒度粗,常需叠加其他维度:
- 用
geoip2模块提取国家码,再用map归类风险等级(如RU→$risk_level = high) - 结合
$http_user_agent或自定义 Header(如X-App-Version),用map标记可信客户端类型 - 多个 map 变量可组合使用,比如只允许
$ip_allowed = 1且$client_trusted = 1的请求通过
注意事项与避坑点
-
map是惰性求值,只在变量首次被引用时计算,性能开销极低 - 不要在
map中调用外部命令或执行耗时操作——它不支持运行时脚本 - 如果 IP 来源是代理链,
$remote_addr会是上一跳地址,务必用real_ip_header X-Forwarded-For并配set_real_ip_from - 黑名单场景建议用
auth_request+ 后端服务,避免map配置过长影响可维护性


















