地理位置封禁需结合geoip识别、ip段批量加载与分层控制:先用geolite2等数据库将国家映射为cidr网段,再通过firewalld富规则或iptables/ipset在边界高效拦截,nginx层补充校验原始地域信息。

针对大型网络实现地理位置封禁,不能只靠单条IP规则硬拦,而需结合精准识别、批量策略和分层控制。核心思路是:用GeoIP定位来源国家/地区 → 将其映射为IP段列表 → 在边界防火墙(如firewalld或iptables)中高效加载并管理这些规则 → 同时在服务层(如Nginx)做兜底校验。
一、用GeoIP数据库自动识别并转换地域为IP段
直接屏蔽“中国”或“美国”这类标签没用,防火墙只认IP地址。必须依赖权威GeoIP数据(如MaxMind GeoLite2),将其转换为CIDR格式的IP段集合:
- 安装geoipupdate工具,并配置license key,定期自动下载最新数据库(建议每周更新)
- 使用geoiplookup或mmdblookup验证单个IP归属;用geoipdump导出某国家全部IPv4网段
- 将CN(中国)、RU(俄罗斯)、KP(朝鲜)等目标区域导出为纯文本IP段列表,例如:
1.0.1.0/24
1.0.2.0/23
1.0.8.0/21 - 对超大列表做合并优化(如用iprange或aggregate工具压缩重复/相邻网段),避免规则膨胀拖慢匹配性能
二、在firewalld中批量加载地域IP段(推荐用于RedHat/CentOS系)
firewalld支持富规则(rich rule),适合处理成百上千条源地址规则,且能与zone机制协同:
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
- 创建专用zone(如geo-block),隔离地域封禁策略,不影响public等主区域
- 用脚本循环导入IP段:
while read net; do firewall-cmd --permanent --zone=geo-block --add-rich-rule="rule family=ipv4 source address=$net reject"; done - 启用该zone绑定到外网接口:
firewall-cmd --permanent --zone=geo-block --add-interface=ens1f0 - 执行firewall-cmd --reload生效;确认加载数量:
firewall-cmd --zone=geo-block --list-rich-rules | wc -l
三、用iptables+nftables做高性能底层封禁(适合高吞吐场景)
当单日地域拦截量超10万IP段时,firewalld富规则可能成为瓶颈,此时应下沉至内核级规则:
- 将整理好的IP段写入/etc/iptables/geo-drop.rules,格式为:
-A INPUT -s 1.0.1.0/24 -j DROP
-A INPUT -s 1.0.2.0/23 -j DROP - 用iptables-restore高速载入:
iptables-restore - 对于nftables用户,生成nft语法更高效:
nft add rule ip filter input ip saddr { 1.0.1.0/24, 1.0.2.0/23 } drop - 务必配合ipset:先创建hash:net类型集合,再把全部地域IP段加入,最后一条规则引用该集合,大幅提升查表速度
四、Nginx层补充校验,应对绕过或代理流量
防火墙只能拦TCP连接建立,但真实请求头(如X-Forwarded-For)可能含原始地域信息,Nginx可二次过滤:
- 编译时启用--with-http_geoip2_module,加载GeoLite2 mmdb文件
- 在http块定义地理变量:
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb { $geoip2_data_country_code country iso_code; } - 在server或location中拦截:
if ($geoip2_data_country_code = "CN") { return 403; } - 注意:仅适用于直连或可信代理环境;若前端有CDN,需解析CDN透传的CF-IPCountry等头部










