nginx基于客户端ip动态分流的核心是使用map指令在http块顶层预定义cidr映射,以$realip_remote_addr(需配置set_real_ip_from)为源变量,输出字符串变量匹配已声明upstream,实现高效查表路由。

要在 Nginx 中基于客户端 IP 实现动态逻辑分流,核心是用 map 指令在 http 块中预定义 IP 段到目标值的映射关系,再在 server 或 location 中引用该变量驱动后续行为(如路由、限流、拒绝等)。它不写在 server 里,也不依赖运行时正则匹配,而是启动即加载的查表机制,轻量且高效。
必须把 map 写在 http 块顶层
这是最常见报错根源:Nginx 启动时若在 server 或 location 中见到 map,直接提示 unknown directive "map"。正确位置是主配置文件(如 /etc/nginx/nginx.conf)的 http { } 块内、所有 server 块之前,通常放在 include 语句之后、upstream 定义之前。
- 宝塔用户需手动编辑主配置,不能把
map塞进站点配置(/www/server/panel/vhost/nginx/xxx.conf) - map 是变量注册行为,不是条件执行逻辑,Nginx 启动时就完成初始化,运行时只查表
选对源变量:$remote_addr 还是 $realip_remote_addr
直连场景下用 $remote_addr 即可;但若前端有 CDN、负载均衡或反向代理,原始客户端 IP 会被压入 X-Forwarded-For,此时必须先配置可信代理链,再使用 $realip_remote_addr:
- 在
http块中添加:set_real_ip_from 10.0.0.0/8;(填你实际的可信代理网段) - 再加:
real_ip_header X-Forwarded-For; - 确保
ngx_http_realip_module已启用(默认编译包含) - 验证方式:加一行
add_header X-Real-IP $realip_remote_addr;看响应头是否为真实用户 IP
用 CIDR 精确匹配 IP 段,设 default 兜底
避免用正则匹配 IP,性能低且易出错。推荐使用 CIDR 格式(如 192.168.1.0/24),并强制设置 default 分支:
- 未匹配时变量为空,会导致
proxy_pass http://$upstream_name解析失败,返回 502 - 示例配置:
default "default_backend";
192.168.10.0/24 "internal_v1";
203.208.60.0/24 "cn_backend";
2a00:1450::/32 "google_crawler";
}
- IPv6 支持原生 CIDR,无需额外模块
- 右侧值是纯字符串,必须与后续声明的
upstream名称完全一致(包括大小写和下划线)
结合 upstream 和 proxy_pass 完成分流
map 输出的是字符串变量,不能直接拼接 URL;必须配合已定义的 upstream 块名使用:
- 在同一个
http块中,紧随map之后定义对应 upstream:
server 10.0.0.10:8080;
}
upstream internal_v1 {
server 10.0.1.5:8080;
server 10.0.1.6:8080;
}
upstream cn_backend {
server 10.0.2.100:8080 weight=2;
}
- 在 location 中引用:
proxy_pass http://$backend_cluster; - 注意:
proxy_pass末尾不能加路径(如/api),否则变量失效;路径应由后端处理或用rewrite统一补全 - 若想对某些 IP 段直接拒绝,可用
map映射为状态码变量,再配合return $deny_code;










