nginx geo模块仅支持基于ip段的粗粒度地域标记,需配合geoip2等数据库实现真实地理位置识别;它在http块中用geo指令定义ip段映射变量,再通过map做语义转换,结合日志记录与访问控制。

Nginx 的 geo 模块本身不直接识别地理位置(如国家、城市),而是根据客户端 IP 地址匹配预定义的 IP 段,从而实现粗粒度的“地理”区分。要真正基于地理位置做访问控制,需配合 IP 归属地数据库(如 GeoIP2)或外部服务,但 geo 模块可作为轻量、高性能的静态 IP 区域标记工具使用。
用 geo 定义 IP 区域变量
在 http 块中使用 geo 指令,为不同 IP 段(支持 CIDR 或范围)分配标识值,例如国家简码:
http {
geo $country_code {
default "ZZ"; # 未匹配时默认值
192.168.1.0/24 "CN"; # 内网测试用 CN
202.96.0.0/16 "CN"; # 某中国 ISP 段
8.8.8.0/24 "US"; # Google DNS(示例)
1.1.1.0/24 "AU"; # Cloudflare(示例)
}
}注意:geo 只支持 IPv4;变量名(如 $country_code)可在后续 if、map 或日志中引用。
结合 map 做语义化映射
geo 输出的是字符串,若需转换为布尔标志或行为策略,推荐用 map 做二次处理:
map $country_code $allow_access {
default 0;
"CN" 1;
"JP" 1;
"KR" 1;
}
<p>server {
location /api/ {
if ($allow_access = 0) {
return 403;
}
proxy_pass <a href="https://www.php.cn/link/65b5b8d1f89bf53a5713bc3afdd83e9e">https://www.php.cn/link/65b5b8d1f89bf53a5713bc3afdd83e9e</a>;
}
}</p>⚠️ 注意:if 在 location 中慎用(Nginx 官方不推荐用于复杂逻辑),更稳妥的方式是用 auth_request 或在 upstream 中通过 proxy_set_header 透传 $country_code,由后端鉴权。
与 GeoIP2 模块配合(推荐生产环境)
若需真实国家/地区/城市级控制,应启用 ngx_http_geoip2_module(需编译安装):
- 下载 MaxMind GeoLite2 City 数据库(
GeoLite2-Country.mmdb) - 配置模块:
http { geoip2 /path/to/GeoLite2-Country.mmdb { $geoip2_data_country_code source=$remote_addr country iso_code; $geoip2_data_country_name source=$remote_addr country names en; } } - 然后像使用
$country_code一样,在if或map中判断$geoip2_data_country_code
限制访问并记录地域信息
可在日志中记录地域变量,便于审计和调试:
log_format geo_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" $country_code;'
<p>access_log /var/log/nginx/access_geo.log geo_log;
</p>同时,用 deny/allow 配合 geo 变量虽不可直接使用,但可通过 map + if + return 或 auth_request 实现等效效果。例如拒绝非白名单地区:
map $country_code $block_region {
~^(?!CN|JP|KR)$ 1; # 正则匹配非 CN/JK/KR 的值
default 0;
}
<p>server {
location / {
if ($block_region) {
return 403 "Access denied from your region.";
}
...
}
}</p>不复杂但容易忽略:所有基于 IP 的地理判断都受代理、CDN、NAT 影响,务必确认 $remote_addr 是真实客户端 IP(需设置 real_ip_header 和 set_real_ip_from)。











