我使用 ipset 来阻止我的服务器上来自许多国家(除法国和法语国家外几乎全世界)的 IP 范围。
我在 ipset 中有两个规则集: badbadworld1 和 badbadworld2
我的主机正在运行docker:一个Nginx docker,以及其他用于不同服务的docker。
# docker -v
Docker version 20.10.17, build 100c701
我想将我的 ipset 添加到 netfilter(在我的主机上),以便仅从我选择的国家/地区访问 Nginx(以及其背后的其他服务)。
当我将 DROP 规则添加到 DOCKER-USER 链时,我没有看到任何数据包被丢弃。
当我将相同的规则添加到 DOCKER 链时,我看到丢弃的数据包。
在这两种情况下,我都可以使用来自被阻止国家/地区的在线代理进行测试。
我可以向两个链都添加 DROP 规则,根据文档,DOCKER-USER 在 DOCKER 之前进行评估,因此在这种情况下,数据包必须由 DOCKER-USER 丢弃,而不是由 DOCKER 链丢弃,对吗?
我测试了这个:
iptables -I DOCKER-USER -m set --match-set badbadworld2 src -j DROP
iptables -I DOCKER-USER -m set --match-set badbadworld1 src -j DROP
iptables -I DOCKER -m set --match-set badbadworld2 src -j DROP
iptables -I DOCKER -m set --match-set badbadworld1 src -j DROP
几分钟后,我的 iptables -v -n -L 如下:
[...]
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
1596 253K DOCKER-ISOLATION-STAGE-1 all -- * * 0.0.0.0/0 0.0.0.0/0
1188 162K ACCEPT all -- * br-a4cbc882767a 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
56 3324 DOCKER all -- * br-a4cbc882767a 0.0.0.0/0 0.0.0.0/0
352 87455 ACCEPT all -- br-a4cbc882767a !br-a4cbc882767a 0.0.0.0/0 0.0.0.0/0
43 2580 ACCEPT all -- br-a4cbc882767a br-a4cbc882767a 0.0.0.0/0 0.0.0.0/0
0 0 DOCKER-USER all -- * * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
0 0 DOCKER all -- * docker0 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
0 0 DROP all -- docker0 docker0 0.0.0.0/0 0.0.0.0/0
[...]
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
10 584 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 match-set badbadworld1 src
1 40 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 match-set badbadworld2 src
2 120 ACCEPT tcp -- !br-a4cbc882767a br-a4cbc882767a 0.0.0.0/0 172.18.0.6 tcp dpt:443
0 0 ACCEPT tcp -- !br-a4cbc882767a br-a4cbc882767a 0.0.0.0/0 172.18.0.6 tcp dpt:80
[...]
Chain DOCKER-USER (1 references)
pkts bytes target prot opt in out source destination
0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 match-set badbadworld1 src
0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 match-set badbadworld2 src
0 0 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
[...]
您可以看到,对于相同的规则,DOCKER 链中丢弃了 11 个数据包,而 DOCKER-USER 中丢弃了 0 个数据包。
注意:我首先测试仅添加到 DOCKER-USER 链,但我很惊讶没有看到任何丢弃的数据包(可以肯定的是,我试图连接来自被封锁国家的在线代理,我可以连接),向两个链都添加规则是没用的,但这只是为了演示问题。
谢谢 !
答案1
跳转到 DOCKER-USER 链之前所有数据包都已被接受或丢弃。
数据包检查从链中的第一条规则开始,直到匹配到某条规则。如果匹配规则的目标是最终规则,如 ACCEPT、DROP、REJECT,数据包将被接受或丢弃,并且不会再对下一条规则进行检查。在 DOCKER-USER 链之前,您的所有数据包都已匹配了多个 ACCEPT 和 DROP。这就是 -j DOCKER-USER 规则的计数器为零的原因。
0 0 DOCKER-USER all -- * * 0.0.0.0/0 0.0.0.0/0
具有 ACCEPT、DROP、REJECT 目标的匹配规则是最终规则- 它停止进一步检查。
在你的情况下,所有被前一个“吃掉”的数据包匹配FORWARD 链中的 ACCEPT 和 DROP 规则,永远不会到达你的 DOCKER-USER 链。
如果 FORWARD 中的所有规则都是自动生成的,并且您无法更改它们的顺序,则可能是 docker 的错误或文档错误。
否则,您应该更改 FORWARD 规则顺序,以便跳转到 DOCKER-USER 位于 ACCEPT ESTABLISHED 规则(#2 规则)之前,或者将您的 DROP 规则直接插入到 ESTABLISHED 之前的 FORWARD 中。
如果 DROP 遵循 ESTABLISHED 规则,则 DROP 将不会立即对已经建立的连接起作用,直到它们明确关闭或超时。
您还应该检查规则的输入/输出接口,因为不清楚您有哪些接口以及您想要丢弃哪些接口的数据包。