iptables和ipset阻断指定区域IP的访问（区域封禁，含Docker）

什么是 ipset

ipset 是 Linux 上一个用来高效管理 IP 地址集合的工具。你可以把它想象成一个 IP 地址的 “容器” 或者 “列表”, 但这个 “列表” 的查找速度非常快，特别适合用在防火墙规则中。

ipset 在这里的作用就是管理 IP 地址集合。

开始之前

以下以中国大陆服务器阻断海外 IP 为例 - Ubuntu 24.04 LTS (Noble Numbat)

确保拥有其他非网络途径可以访问服务器，以便恢复错误的 iptables 规则，比如 VNC 等

首先，我们需要拥有一个指定区域的 IP 集合，可以通过如下命令进行获取：

Copy
# *也可以更换为其他的更全面的IP集合
# 下载中国IP地址集合
wget -P . http://www.ipdeny.com/ipblocks/data/countries/cn.zone

其次，安装 ipset

Copy
sudo apt install ipset -y

最后，创建集合

Copy
# 创建一个名为cnip的集合
ipset -N cnip hash:net
# 导入刚刚下载的IP集合的IP到cnip集合中
for i in $(cat ./cn.zone ); do ipset -A cnip $i; done

开始阻断

为确保规则生效，需要清链，请勿直接在生产环境进行操作，注意备份

Copy
# 备份原有规则
iptables-save > ~/iptables.bak
# 清链
iptables -F
iptables -X
# 允许本地回环
iptables -A INPUT -i lo -j ACCEPT
# 阻断所有海外IP（不符合cnip集合的IP）（仅允许中国IP（cnip集合内的IP）访问）
iptables -A INPUT -m set ! --match-set cnip src -j DROP
# 或者不允许中国IP访问，可以把感叹号“! ”去掉即可

注意

首先，注意备份原有规则，防止出现问题。

其次，需要经常或者定期更新 IP 地址库。

再其次，Docker 等特殊链需要自行思考处理方式。

最后，服务器重启会导致规则丢失，可以编写个脚本去开机自动执行 iptabes 规则。

更新 2025-02-12

今天又尝试了一下 Docker 屏蔽海外的 IP（紧接上文）

如果容器是主机网络模式（Host）则会与宿主机一致，无需单独更改，一下情况只针对桥模式（Bridge ）

首先我们需要明白，Docker 桥流量在什么链之后会被地址转换（此处特指 SNAT，源地址转换），SNAT 过的地址是判断不了是否来自于海外，而 SNAT 发生的地方就是 FORWARD 链的后一个链，即 POSTROUTING 链（PREROUTING→FORWARD→POSTROUTING）

补充：DNAT（目的地址转换）是发生在 FORWARD 链的前一个链，即 PREROUTING 链

理论存在，实践开始

我们只需要判断源地址，所以我们只需要在 FORWARD 链上面做一些手脚。

首先，我们把原有的 iptables 规则备份：iptables-save > ~/iptables.bak

然后，复制出来一个新的规则（名为 iptables-only-allow-cnip-docker），并将原有的 2 个规则注释掉：

Copy
# 含义是将转发的流量直接交给DOCKER的链
# -A FORWARD -j DOCKER-USER
# -A FORWARD -j DOCKER-ISOLATION-STAGE-1

注释完成之后，将如下规则填入到注释掉的 2 个规则的下面

iptables 的规则是按顺序执行的

Copy
# 含义是将来自于eth0网卡且匹配cnip的IP集合的流量交给DOCKER相关的链（仅允许来自于cnip的IP）
# 注：eth0为我的本机网卡，如有别的网卡，自行添加或者更改
-A FORWARD -i eth0 -m set --match-set cnip src -j DOCKER-USER
-A FORWARD -i eth0 -m set --match-set cnip src -j DOCKER-ISOLATION-STAGE-1
# 丢弃eth0网卡上不匹配cnip的IP集合流量的封包（阻断来自于非cnip的IP）
# 注：eth0为我的本机网卡，如有别的网卡，自行添加或者更改
-A FORWARD -i eth0 -m set ! --match-set cnip src -j DROP

修改完成之后，将规则导入至 iptables 使其生效

Copy
iptables-restore < ~/iptables-only-allow-cnip-docker

效果

Docker 桥网络

本机网络