Nginx需借助GeoIP2等第三方数据库实现国家白名单控制:先映射IP为国家代码,再匹配允许的ISO码并拒绝其余请求;配置含模块编译、数据库加载、map白名单及if拦截,注意CDN下需透传真实IP。

Nginx 本身不直接识别国家或地区,必须借助第三方 IP 地理位置数据库(如 GeoIP2 或 MaxMind)配合模块实现白名单国家访问控制。核心思路是:将 IP 映射为国家代码 → 在 Nginx 配置中匹配允许的国家代码 → 拒绝其余请求。
1. 安装 GeoIP2 模块与数据文件
推荐使用更精准、持续更新的 GeoIP2(替代已停止维护的旧版 GeoIP):
- 编译 Nginx 时需添加
--add-module=/path/to/ngx_http_geoip2_module(需先下载该模块) - 从 MaxMind 官网注册账号,免费下载
GeoLite2 Country数据库(GeoLite2-Country.mmdb) - 将
.mmdb文件放到服务器固定路径,例如/usr/share/GeoIP/GeoLite2-Country.mmdb
2. 配置 geoip2 指令映射国家代码
在 http 块中加载数据库并提取国家 ISO 代码:
http {
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
$geoip2_data_country_code source=$remote_addr country iso_code;
}
<pre class="brush:php;toolbar:false;"># 可选:记录国家码用于调试(临时加在日志格式里)
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$geoip2_data_country_code"';}
3. 设置国家白名单并拦截非授权请求
在 server 或 location 块中用 map 构建允许列表,再用 deny/allow 或 return 403 控制访问:
map $geoip2_data_country_code $allowed_country {
default 0;
CN 1; # 中国
JP 1; # 日本
KR 1; # 韩国
US 1; # 美国
}
<p>server {
listen 80;
server_name example.com;</p><pre class="brush:php;toolbar:false;"># 方式一:用 satisfy + allow/deny(需启用 auth_basic 模块支持)
# satisfy any;
# allow 127.0.0.1;
# deny all;
# auth_basic off;
# 方式二(推荐):直接返回 403(更简洁,无需额外模块)
if ($allowed_country = 0) {
return 403;
}
location / {
root /var/www/html;
index index.html;
}}注意:Nginx 中 if 在 location 外使用有局限性,若需精细控制(如仅保护 API 路径),可将 if 移入对应 location 块;或改用 auth_request 子请求方式做更安全的鉴权。
4. 验证与维护要点
- 用境外代理或不同国家 IP 测试是否被正确放行/拦截(可用
curl -x http://jp-proxy:8080 http://your-site.com) - 定期更新
.mmdb文件(MaxMind 每月发布新版,建议写脚本自动下载+重载 Nginx) - 注意 CDN 场景:若网站前端有 CDN(如 Cloudflare),
$remote_addr是 CDN 节点 IP,需改用$http_cf_ipcountry(Cloudflare 提供)或配置 CDN 透传真实 IP(如X-Forwarded-For+set_real_ip_from)


















