Linux中可通过ipset结合GeoIP数据按国家封禁IP:下载解析某国IP段→导入ipset集合→用iptables/nftables引用DROP;需确保ipset、内核模块等前提,并注意数据时效性、IPv4/v6支持及性能边界。

在 Linux 中通过 ipset 结合 GeoIP 数据实现按国家封禁 IP 流量,核心思路是:下载并解析某国所有公网 IP 段 → 导入 ipset 集合 → 用 iptables 或 nftables 引用该集合进行 DROP。整个流程可脚本化,做到“一键封禁”,但需注意数据时效性、IPv4/IPv6 支持、内核模块依赖及性能边界。
准备前提:确认系统支持与基础工具
确保以下组件已安装并启用:
-
ipset 工具:运行
ipset --version验证;若未安装,Debian/Ubuntu 执行sudo apt install ipset,CentOS/RHEL 使用sudo yum install ipset或dnf install ipset -
内核模块加载:检查
ip_set_hash_net是否就绪:lsmod | grep ip_set_hash_net;如无输出,执行sudo modprobe ip_set_hash_net - curl/wget & unzip/tar:用于下载 GeoIP 数据
-
Python(可选但推荐):用于解析 CIDR 或处理 MaxMind 的 GeoLite2 格式(需
geoip2库)
获取可信的国家级 IP 段数据源
不建议手动维护 IP 段。推荐以下两种主流方式:
-
APNIC/IANA 公共路由数据:访问 APNIC 最新 delegation 文件,筛选
country=CN(中国)、JP(日本)等字段,提取 IPv4 前缀(如1.0.1.0/24)。适合批量自动化,但不含 IPv6 且粒度较粗 -
MaxMind GeoLite2 Country(免费版):注册 MaxMind 账号 下载
GeoLite2-Country-CSV.zip,解压后用 Python +geoip2或 shell 脚本提取指定国家的所有 CIDR(含 IPv4/IPv6)。精度高、更新勤(每月一次),但需遵守其 EULA(禁止直接分发导出结果)
构建并加载国家 IP 集合(以 China 为例)
假设你已获得一个名为 cn-ips.txt 的纯文本文件,每行一个 CIDR(如 1.0.1.0/24):
# 创建名为 cn_block 的 hash:net 类型集合(支持 CIDR) sudo ipset create cn_block hash:net family inet hashsize 4096 maxelem 65536 <h1>批量添加 IP 段(跳过空行和注释)</h1><p>while IFS= read -r cidr; do [[ -z "$cidr" || "$cidr" =~ ^# ]] && continue sudo ipset add cn_block "$cidr" 2>/dev/null done </p><h1>查看是否成功导入(显示条目数)</h1><p>sudo ipset list cn_block | head -n 5 </p>
⚠️ 注意:若含 IPv6,需另建 family inet6 集合(如 cn_block6),iptables 不支持 IPv6,须改用 ip6tables 或统一迁移到 nftables。
在防火墙规则中调用并生效封禁
使用 iptables 引用集合(IPv4):
# 在 INPUT/OUTPUT/FORWARD 链顶部插入 DROP 规则(谨慎!先测试) sudo iptables -I INPUT -m set --match-set cn_block src -j DROP sudo iptables -I FORWARD -m set --match-set cn_block src -j DROP <h1>保存规则(不同发行版命令不同)</h1><h1>Debian/Ubuntu:</h1><p>sudo iptables-save > /etc/iptables/rules.v4</p><h1>CentOS/RHEL(使用 iptables-services):</h1><p>sudo service iptables save </p>
更现代的做法是用 nftables(推荐):
# 定义地址集(自动兼容 IPv4/IPv6,若已分别建好两个集合)
nft add table inet filter
nft add set inet filter cn_block { type ipv4_addr\; }
nft add element inet filter cn_block { 1.0.1.0/24, 112.64.0.0/11 }
<h1>添加规则</h1><p>nft add chain inet filter input { type filter hook input priority 0 \; }
nft add rule inet filter input ip saddr @cn_block drop
</p>
完成之后,来自该国的入向流量将被静默丢弃。建议搭配 tcpdump -i any src net 1.0.1.0/24 实时验证效果。
整个过程可封装为带参数的 Bash 脚本(如 ./block-country.sh CN),自动下载、解析、创建集合、加载规则。关键点在于数据源可靠性、集合容量预估(避免 maxelem 不足)、以及封禁前务必在测试环境验证,避免误杀管理 IP 或 CDN 回源地址。不复杂但容易忽略。











