跳转至

基于 GeoIP2 的国家封锁

通过 MaxMind 的准确地理定位数据库控制按国家的访问。


  • 阻止恶意行为者


    在攻击到达您的应用程序之前,阻止来自高风险国家的攻击

  • 合规准备


    强制执行 GDPR、许可或法律要求的地理限制

  • 零开销


    内存数据库查找——无外部 API 调用或延迟

  • 准确数据


    MaxMind GeoIP2 数据库具有 99.8% 的国家准确性


前提条件

您需要一个 免费的 MaxMind 账户 来下载 GeoIP2 数据库:

  1. maxmind.com/en/geolite2/signup 注册
  2. 在您的账户中生成许可证密钥
  3. 保存以便于自动更新设置

快速设置

第一步:安装 GeoIP2 模块

# 安装 GetPageSpeed 仓库
dnf -y install https://extras.getpagespeed.com/release-latest.rpm

# 安装 GeoIP2 模块和自动数据库更新程序
dnf -y install nginx-module-geoip2 geoipupdate

/etc/nginx/nginx.conf 中启用:

load_module modules/ngx_http_geoip2_module.so;

第二步:配置数据库更新

编辑 /etc/GeoIP.conf

AccountID YOUR_ACCOUNT_ID
LicenseKey YOUR_LICENSE_KEY
EditionIDs GeoLite2-Country GeoLite2-City

下载数据库:

geoipupdate

启用每周自动更新:

systemctl enable --now geoipupdate.timer

第三步:配置 NGINX

/etc/nginx/nginx.confhttp 块中添加:

# 加载 GeoIP2 数据库
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
    auto_reload 60m;
    $geoip2_country_code country iso_code;
    $geoip2_country_name country names en;
}

第四步:封锁国家

# 封锁俄罗斯、中国、朝鲜
map $geoip2_country_code $blocked_country {
    default 0;
    RU 1;
    CN 1;
    KP 1;
}

server {
    # ... 您的服务器配置 ...

    if ($blocked_country) {
        return 403;
    }
}
# 仅允许美国、英国、加拿大、澳大利亚
map $geoip2_country_code $allowed_country {
    default 0;
    US 1;
    GB 1;
    CA 1;
    AU 1;
}

server {
    # ... 您的服务器配置 ...

    if ($allowed_country = 0) {
        return 403;
    }
}
map $geoip2_country_code $blocked_country {
    default 0;
    RU 1;
    CN 1;
}

server {
    error_page 403 /geo-blocked.html;

    location = /geo-blocked.html {
        internal;
        root /var/www/error-pages;
    }

    if ($blocked_country) {
        return 403;
    }
}

重新加载 NGINX:

nginx -t && systemctl reload nginx

测试

# 使用已知 IP 测试
curl -H 'X-Forwarded-For: 8.8.8.8' https://example.com
# 应该可以工作(Google DNS - 美国)

curl -H 'X-Forwarded-For: 77.88.8.8' https://example.com
# 应该被封锁(Yandex DNS - 俄罗斯,如果 RU 被封锁)

本地测试

本地/私有 IP 返回空的国家代码。请使用真实的公共 IP 进行测试。


高级用法

在代理/CDN 后使用真实客户端 IP

geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
    $geoip2_country_code source=$http_x_forwarded_for country iso_code;
}

针对不同路径使用不同规则

# 除 API 外的所有地方都封锁
location / {
    if ($blocked_country) {
        return 403;
    }
    # ... 正常配置 ...
}

location /api/ {
    # API 可从任何地方访问
    # ... api 配置 ...
}

记录国家信息

log_format geo '$remote_addr - $geoip2_country_code - $request';
access_log /var/log/nginx/geo.log geo;

按国家限速

# 对高风险国家实施更严格的限制
map $geoip2_country_code $limit_key {
    default $binary_remote_addr;
    RU $binary_remote_addr$geoip2_country_code;
    CN $binary_remote_addr$geoip2_country_code;
}

limit_req_zone $limit_key zone=geo_limit:10m rate=10r/s;

常见国家代码

代码 国家 代码 国家
US 美国 DE 德国
GB 英国 FR 法国
CA 加拿大 AU 澳大利亚
CN 中国 RU 俄罗斯
IN 印度 BR 巴西
JP 日本 KR 韩国
KP 朝鲜 IR 伊朗

完整列表: ISO 3166-1 alpha-2


故障排除

国家始终为空
  • 检查数据库路径是否存在: ls -la /usr/share/GeoIP/
  • 验证模块是否加载: nginx -V 2>&1 | grep geoip2
  • 检查 IP 是否为私有/本地主机
检测到错误的国家
  • 更新数据库: geoipupdate
  • 检查是否在 CDN/代理后(使用 X-Forwarded-For
  • MaxMind 的准确性: ~99.8% 的国家
数据库未更新
  • 检查定时器: systemctl status geoipupdate.timer
  • 验证 /etc/GeoIP.conf 中的凭据
  • 手动运行: geoipupdate -v

相关内容

  • GeoIP2 模块


    完整的指令参考

    文档

  • ModSecurity WAF


    完整的 Web 应用防火墙

    文档

  • 限速


    防止滥用

    文档