Nginx 中 geo 指令用于基于客户端真实 IP 定义变量,实现地域分流;必须置于 http 块,配合 real_ip 模块还原真实 IP,再通过 map 映射为上游组名用于 proxy_pass。

在 Nginx 中,geo 指令可用于根据客户端 IP 地址定义变量,是实现地域分流(如国内走 A 节点、海外走 B 节点)的基础手段之一。它不直接做转发,而是配合 map、if 或 upstream 选择逻辑,完成差异化路由。
geo 指令的基本用法和作用范围
geo 必须放在 http 块中,不能写在 server 或 location 内。它的核心功能是:基于客户端真实 IP(需确保已正确获取,例如通过 real_ip 模块还原),匹配预设的 IP 段,为指定变量赋值。
- 默认匹配失败时变量为空或设为默认值(用
default显式指定) - 支持 CIDR 格式(如
1.2.3.0/24)、IP 范围(1.2.3.4-1.2.3.255)、单 IP,也支持使用外部文件(geo $country /path/to/ipdb.conf;) - 不支持正则表达式,匹配效率高,适合大规模 IP 判定
结合 map 实现语义化地域标识
直接在 geo 中写业务逻辑不够灵活,推荐先用 geo 划分粗粒度区域(如 cn / other),再用 map 映射为更易读的值或上游组名:
http {
geo $is_cn {
default 0;
include geo-cn.conf; # 包含中国所有公网 IP 段
}
<pre class="brush:php;toolbar:false;">map $is_cn $upstream_backend {
1 backend_cn;
0 backend_oversea;
}
}
这样后续可在 proxy_pass 中直接引用:proxy_pass http://$upstream_backend;,实现自动分流。
注意真实客户端 IP 的准确性
若 Nginx 前有 CDN、LB 或反向代理,$remote_addr 将是上一跳地址,导致 geo 判定失效。必须配合以下配置还原真实 IP:
- 启用
ngx_http_realip_module(通常已内置) - 设置
set_real_ip_from声明可信代理网段 - 用
real_ip_header指定携带原始 IP 的请求头(如X-Forwarded-For或X-Real-IP)
示例:
set_real_ip_from 10.0.0.0/8; set_real_ip_from 192.168.0.0/16; real_ip_header X-Forwarded-For; real_ip_recursive on;
常见问题与避坑提示
geo 变量在请求处理早期生成,但部分变量(如 $host、$request_uri)在 later 阶段才可用,因此不要在 geo 块中依赖它们。另外:
-
geo不支持嵌套或动态加载,IP 库更新需 reload Nginx - 避免在
geo中写过多细粒度规则(如按省划分),会显著增大内存占用和匹配耗时;建议用外部 GeoIP 库(如 maxmind)+ngx_http_geoip2_module替代 - 测试时用
curl -H "X-Forwarded-For: 1.2.3.4" http://test.com模拟不同地区请求,配合add_header X-Geo $is_cn;方便验证










