核心是编译安装ngx_http_geoip2_module模块、配置GeoLite2-City.mmdb数据库、在http块中定义$geoip2_data_province_name和$geoip2_data_city_name等中文变量,并通过log_format或fastcgi_param等注入日志或透传至后端。

使用 Nginx 的 ngx_http_geoip2_module 模块解析访客的省市信息,核心是:编译安装模块、配置 GeoIP2 数据库、在 Nginx 配置中定义变量并使用。它比旧版 geoip 模块更准确、支持 IPv6 和更细粒度的地理数据(如省、市、区、经纬度等)。
一、确认 Nginx 已加载 geoip2 模块
该模块不是 Nginx 官方默认模块,需手动编译或通过包管理器安装带模块的版本:
- Ubuntu/Debian:推荐用
nginx-extras(含 geoip2)或从 sury 仓库 安装; - CentOS/RHEL:可用 EPEL +
nginx-mod-http-geoip2(RHEL 8+),或自行编译; - 源码编译:下载 模块源码,在 configure 时加
--add-dynamic-module=../ngx_http_geoip2_module,再make && make install; - 验证是否加载成功:
nginx -V 2>&1 | grep -o geoip2或nginx -V 2>&1 | grep -o with-http-geoip2-module,有输出即表示支持。
二、下载并配置 GeoIP2 City 数据库
MaxMind 提供免费的 GeoLite2 City 数据库(需注册账号下载),注意选择 .mmdb 格式(非旧版 .dat):
- 下载地址:https://www.php.cn/link/c4620e8a4aaa1f62e739608c2a866f9f;
- 解压后得到
GeoLite2-City.mmdb,建议存放到固定路径,例如:/usr/share/GeoIP/GeoLite2-City.mmdb; - Nginx 需有读取权限(如
chown nginx:nginx /usr/share/GeoIP/GeoLite2-City.mmdb); - 在
http{}块中添加配置:
geoip2 /usr/share/GeoIP/GeoLite2-City.mmdb {
$geoip2_data_country_code source=$remote_addr country iso_code;
$geoip2_data_country_name source=$remote_addr country names zh-CN;
$geoip2_data_province_code source=$remote_addr subdivisions 0 iso_code;
$geoip2_data_province_name source=$remote_addr subdivisions 0 names zh-CN;
$geoip2_data_city_name source=$remote_addr city names zh-CN;
$geoip2_data_latitude source=$remote_addr location latitude;
$geoip2_data_longitude source=$remote_addr location longitude;
}说明:subdivisions 0 表示一级行政区(中国即“省”),部分城市(如北京、上海、重庆、天津)属于直辖市,也归在此层级;names zh-CN 启用中文名称(需数据库含中文翻译,GeoLite2 免费版支持)。
三、在 server 或 location 中使用解析结果
定义好变量后,可直接用于日志、响应头、条件判断或代理转发:
- 写入 access_log(需先定义 log_format):
log_format geoip '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$geoip2_data_country_name/$geoip2_data_province_name/$geoip2_data_city_name';- 透传到后端(如 PHP/FastCGI 或反向代理):
fastcgi_param GEOIP_COUNTRY_NAME $geoip2_data_country_name; fastcgi_param GEOIP_PROVINCE_NAME $geoip2_data_province_name; fastcgi_param GEOIP_CITY_NAME $geoip2_data_city_name;
- 根据地域做简单跳转或限流(配合 map 或 if,但 if 在 location 中慎用):
map $geoip2_data_province_name $is_china_east {
default 0;
"江苏省" 1;
"浙江省" 1;
"上海市" 1;
}
# 然后在 location 中:
if ($is_china_east) {
set $custom_header "east-china";
}四、常见问题与注意点
- IPv6 支持:模块原生支持,无需额外配置,只要数据库含 IPv6 记录(GeoLite2 默认包含);
-
代理环境(如 CDN 或负载均衡):必须确保
$remote_addr是真实客户端 IP,否则需配合real_ip模块和set_real_ip_from设置可信源,并启用real_ip_header X-Forwarded-For; - 性能影响:mmdb 查询极快(微秒级),但频繁调用多个字段仍略增开销,建议按需定义变量,避免冗余字段;
-
中文乱码:Nginx 日志或响应头若出现中文乱码,请确认系统 locale(如
zh_CN.UTF-8)已启用,且终端/查看工具支持 UTF-8; -
数据库更新:MaxMind 每月更新数据库,建议用脚本定期下载替换,并 reload Nginx(
nginx -s reload)。


















