旧版 ngx_http_geoip_module 已废弃,必须使用 ngx_http_geoip2_module + GeoLite2-Country.mmdb;需确认 Nginx 版本≥1.11.3、模块已编译加载、数据库路径权限正确、变量映射配置无误,并通过 map 实现安全分流,同时确保真实客户端 IP 可用。

旧版 ngx_http_geoip_module 已在 Nginx 1.11.3+ 中废弃,现在必须用 ngx_http_geoip2_module + GeoLite2-Country.mmdb,否则配置直接报 unknown directive "geoip_country" 错误。
确认 Nginx 版本与模块支持状态
执行 nginx -v 看版本,低于 1.18 的建议先升级;再执行 nginx -V 2>&1 | grep -o "geoip2"。无输出说明模块未加载成功——不是“装了就行”,而是必须参与编译或动态加载。
- Ubuntu/Debian 用户别直接装
nginx-full,它默认不含geoip2,仍需手动编译 - 宝塔用户注意:面板自带的 Nginx 多数是“精简版”,
nginx -V输出里若没--add-module=...指向ngx_http_geoip2_module,就等于没启用 - CentOS/RHEL 上通过
yum install nginx-mod-http-geoip安装的是旧版geoip模块,和.mmdb数据库不兼容
编译 ngx_http_geoip2_module 到 Nginx
核心动作是重编译,不是安装新包。必须复用原有 configure 参数,否则会丢 SSL、HTTP/2、stream 等关键模块。
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
- 先用
nginx -V复制完整 configure 参数(含所有--with-xxx和--prefix) - 下载并解压对应版本 Nginx 源码,再
git clone https://github.com/leev/ngx_http_geoip2_module.git - 执行 configure 时追加
--add-module=/path/to/ngx_http_geoip2_module,其他参数一个都不能少 -
make后只替换二进制:cp objs/nginx /usr/sbin/nginx(或宝塔路径/www/server/nginx/sbin/nginx),严禁make install
配置 geoip2 数据库与国家变量映射
数据库路径、权限、变量定义三者缺一不可。常见错误是 $geoip2_data_country_code 始终为空,基本都卡在这步。
- 把
GeoLite2-Country.mmdb放到如/www/server/geoip2/GeoLite2-Country.mmdb,确保nginxworker 进程可读(chown nginx:nginx+chmod 644) - 在
http块顶层写:geoip2 /www/server/geoip2/GeoLite2-Country.mmdb { $geoip2_data_country_code source=$remote_addr country iso_code; $geoip2_data_country_name source=$remote_addr country names en; } - 变量名(如
$geoip2_data_country_code)可自定义,但后续所有引用必须完全一致;source=$remote_addr不能漏,否则拿不到真实 IP
用 map 实现安全高效的地域分流
直接在 location 里写 if ($geoip2_data_country_code != "CN") { return 403; } 不仅性能差,还可能触发 Nginx 的 if 陷阱(比如 rewrite 循环、变量未初始化)。
- 必须把
map块写在http块顶层,不能嵌套在server内 - 例如白名单分流:
map $geoip2_data_country_code $route_target { default "/default"; CN "/cn"; JP "/jp"; US "/us"; } - 然后在
location /中用try_files $route_target$uri $route_target/index.html =404;,比一堆if更可靠 - 若需拦截,用
if ($route_target = "/default") { return 403; },比直接判断国家码更清晰
最易被忽略的是真实客户端 IP 的获取——如果 Nginx 前有 CDN 或反向代理,$remote_addr 是上一级 IP,必须配合 set_real_ip_from 和 real_ip_header 把真实 IP 提上来,否则所有地理判断都是错的。

















