基于 GeoIP2 的国家封锁
通过 MaxMind 的准确地理定位数据库控制按国家的访问。
-
阻止恶意行为者
在攻击到达您的应用程序之前,阻止来自高风险国家的攻击
-
合规准备
强制执行 GDPR、许可或法律要求的地理限制
-
零开销
内存数据库查找——无外部 API 调用或延迟
-
准确数据
MaxMind GeoIP2 数据库具有 99.8% 的国家准确性
前提条件
您需要一个 免费的 MaxMind 账户 来下载 GeoIP2 数据库:
- 在 maxmind.com/en/geolite2/signup 注册
- 在您的账户中生成许可证密钥
- 保存以便于自动更新设置
快速设置
第一步:安装 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.conf 的 http 块中添加:
# 加载 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