nginx中通过map指令结合geoip2模块实现地理位置访问控制是核心方式,需先加载.mmdb数据库并定义$geoip2_data_country_code等变量,再用map映射国家代码为布尔值、upstream名或重定向地址,最后在location中配合return或proxy_pass执行精准控制,全程服务端完成、高性能且不可绕过。

直接在 Nginx 配置中用 map 指令结合 GeoIP 数据,是实现轻量、高效、服务端驱动的地理位置访问控制与动态路由的核心方式。它不依赖 JavaScript 或后端业务代码,所有判断在请求进入 upstream 前完成,性能高且不可绕过。
前提:启用并加载 GeoIP 数据库
Nginx 本身不内置地理定位能力,需通过模块支持:
- OpenResty 用户默认含
ngx_http_geoip2_module(推荐),支持 MaxMind GeoLite2 格式(.mmdb); - 传统 Nginx 若编译时含
--with-http_geoip_module,则支持旧版 GeoIP.dat(已停止更新,不建议新项目使用); - 确认模块已加载:运行
nginx -V 2>&1 | grep -o with-http_geoip或检查nginx -V输出中是否有geoip2。
配置示例(以 geoip2 为例):
load_module modules/ngx_http_geoip2_module;
http {
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
$geoip2_data_country_code source=$remote_addr country iso_code;
$geoip2_data_city_name source=$remote_addr city names en;
}
}
用 map 构建国家/地区维度的路由开关
map 指令可将原始变量(如 $geoip2_data_country_code)映射为自定义变量,用于后续条件判断或重定向。它支持精确匹配、正则、默认值,且惰性求值,开销极低。
常见用途:
- 禁止特定国家访问 → 映射为布尔标记;
- 按国家分流到不同后端集群 → 映射为 upstream 名称;
- 为不同地区设置差异化缓存策略或响应头 → 映射为 header 值。
示例:将中国、日本、韩国用户映射到 asia_backend,美国用户映射到 us_backend,其余走默认 default_backend
map $geoip2_data_country_code $upstream_group {
default default_backend;
CN asia_backend;
JP asia_backend;
KR asia_backend;
US us_backend;
}
结合 if / return / proxy_pass 实现精准控制
map 生成的变量可直接用于 location 块内的逻辑分支。注意:if 在 location 中安全可用,但避免在 server 级别滥用。
场景一:国家级跳转(302)
map $geoip2_data_country_code $redirect_target {
default "";
RU https://example.com/russia-unavailable;
IR https://example.com/restricted;
}
server {
location / {
if ($redirect_target) {
return 302 $redirect_target;
}
proxy_pass http://default_backend;
}
}
场景二:动态代理目标(按地区选 upstream)
upstream asia_backend { server 10.0.1.10:8080; }
upstream us_backend { server 10.0.2.20:8080; }
upstream default_backend { server 10.0.3.30:8080; }
server {
location /api/ {
proxy_pass http://$upstream_group;
proxy_set_header X-Client-Country $geoip2_data_country_code;
}
}
进阶:组合城市+国家做精细化策略
GeoIP2 支持城市级字段,map 可嵌套使用或联合判断(借助 map 的多级匹配能力):
geoip2 /usr/share/GeoIP/GeoLite2-City.mmdb {
$geoip2_data_country_code country iso_code;
$geoip2_data_city_name city names en;
}
map "$geoip2_data_country_code:$geoip2_data_city_name" $is_shanghai {
default 0;
"CN:Shanghai" 1;
}
map "$geoip2_data_country_code:$geoip2_data_city_name" $is_silicon_valley {
default 0;
"US:San Jose" 1;
"US:Mountain View" 1;
"US:Palo Alto" 1;
}
随后可在 location 中:
if ($is_shanghai) {
set $backend_override shanghai_special;
}
if ($is_silicon_valley) {
set $backend_override sv_canary;
}
再配合 proxy_pass http://$backend_override 完成超细粒度路由。










