nginx需借助geoip2模块+geolite2数据库实现精准国家屏蔽,或用静态cidr列表作粗粒度拦截;推荐方案一,因其准确、可维护、解耦业务;备选方案二时效差、易误伤。

Nginx 本身不内置地理 IP 库,无法直接识别“海外”或“高风险国家”,但可通过 结合外部 IP 地理数据库(如 GeoLite2)+ ngx_http_geoip2_module,实现按国家/地区精准屏蔽。这是当前生产环境最可靠、可维护的方式。若暂无条件编译该模块,则可用静态 IP 段列表配合 geo 或 map 指令做粗粒度拦截——但需注意:纯靠手动维护 IP 段易过期、漏判且运维成本高。
以下分两种实用路径说明,优先推荐方案一:
使用 GeoIP2 模块动态屏蔽指定国家
前提:Nginx 已安装 ngx_http_geoip2_module(需 OpenResty 或自行编译),并下载了 MaxMind 的免费 GeoLite2 Country 数据库(GeoLite2-Country.mmdb)。
-
配置 geoip2 模块加载数据库与变量
http { geoip2 /path/to/GeoLite2-Country.mmdb { $geoip2_data_country_code source=$remote_addr country iso_code; } # 定义需屏蔽的国家代码(例如:CN 保留,屏蔽 RU、KP、MM、IQ、IR、SY 等常被用于僵尸网络的国家) map $geoip2_data_country_code $blocked_country { default 0; RU 1; # 俄罗斯 KP 1; # 朝鲜 MM 1; # 缅甸 IQ 1; # 伊拉克 IR 1; # 伊朗 SY 1; # 叙利亚 AO 1; # 安哥拉(部分扫描器活跃区) SS 1; # 南苏丹 } } -
在 server 或 location 中拦截
server { location / { if ($blocked_country) { return 444; # 静默关闭连接(不发响应),比 403 更节省资源 } # 正常代理或服务 proxy_pass http://backend; } }✅ 优势:实时、准确、支持增量更新数据库;屏蔽逻辑与业务配置解耦;不影响正常用户(如海外华人用非本地 IP 访问,只要不在黑名单国家即放行)。
⚠️ 注意:if 在 location 中慎用,但用于简单布尔判断(如 $var 非空)是安全的;return 444 是 Nginx 原生指令,无额外开销。
用静态 IP 段列表做补充防护(无 GeoIP 环境下的备选)
适用于临时应急或轻量部署,但不能替代 GeoIP 方案。
-
准备高风险 IP 段列表(如从威胁情报平台导出) 保存为
/etc/nginx/conf.d/blocked-cidr.conf:# 示例:部分已知恶意活跃网段(仅示意,请定期更新) deny 185.193.128.0/18; deny 193.188.200.0/21; deny 45.144.0.0/16; deny 103.224.182.0/24; # ……更多 CIDR,每行一个
-
在 http 或 server 块中引入
http { include /etc/nginx/conf.d/blocked-cidr.conf; server { location / { # 若匹配到 deny 规则,自动返回 403 proxy_pass http://backend; } } }✅ 优势:零依赖,生效快。
❌ 局限:IP 段时效性差;无法区分“海外用户”和“攻击源”;维护成本高;易误伤(如某国 CDN 节点被封)。
补充建议:增强效果的协同配置
屏蔽只是第一道防线,建议搭配以下措施形成纵深防御:
- 对所有被屏蔽国家的请求,同时启用严格限流:
limit_req_zone $geoip2_data_country_code zone=by_country:10m rate=1r/s; limit_req zone=by_country burst=3 nodelay;
- 关闭不必要的 HTTP 方法(如 TRACE、OPTIONS):
if ($request_method !~ ^(GET|HEAD|POST|PUT|DELETE|PATCH|OPTIONS)$ ) { return 444; } - 隐藏服务器标识,减少指纹暴露:
server_tokens off;
不复杂但容易忽略:屏蔽策略上线后,务必用 nginx -t && nginx -s reload 验证,并监控 access log 中 444 或 403 的命中率,避免误杀真实流量。











