我正在调试一个不是我写的 iptables 设置。这个设置应该为路由器本身上运行的一些 Docker 容器(Portainer 和 Nginx Proxy Manager)提供防火墙,但出了点问题,两个 Docker 容器都无法向 WAN 提供网站服务。iptables -L -v -n
输出如下所示:
root@FriendlyWrt:/proc/sys/net/bridge# iptables -L -v -n
# Warning: iptables-legacy tables present, use iptables-legacy to see them
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
1400K 251M DOCKER-USER all -- * * 0.0.0.0/0 0.0.0.0/0
1397K 251M DOCKER-ISOLATION-STAGE-1 all -- * * 0.0.0.0/0 0.0.0.0/0
5815 404K ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
2580 116K DOCKER all -- * docker0 0.0.0.0/0 0.0.0.0/0
15447 7639K ACCEPT all -- docker0 !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
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain DOCKER (1 references)
pkts bytes target prot opt in out source destination
83 4836 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.2 tcp dpt:9443
1 60 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.2 tcp dpt:8000
29 1740 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.3 tcp dpt:443
1 60 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.3 tcp dpt:81
2 120 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.3 tcp dpt:80
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
pkts bytes target prot opt in out source destination
15447 7639K DOCKER-ISOLATION-STAGE-2 all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
1397K 251M RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-ISOLATION-STAGE-2 (1 references)
pkts bytes target prot opt in out source destination
0 0 DROP all -- * docker0 0.0.0.0/0 0.0.0.0/0
15447 7639K RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-MAN (1 references)
pkts bytes target prot opt in out source destination
8395 519K RETURN all -- br-lan docker0 0.0.0.0/0 0.0.0.0/0
2805 167K DROP all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate INVALID,NEW
236 59251 RETURN all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
1388K 251M RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-USER (1 references)
pkts bytes target prot opt in out source destination
1400K 251M DOCKER-MAN all -- * * 0.0.0.0/0 0.0.0.0/0
236 59251 REJECT all -- eth0 docker0 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
1397K 251M RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
看起来在“forward”链的开头,所有流量都被发送到“docker-user”链,然后在下一个规则中,所有剩余流量都被发送到“docker-isolation-stage-1”链。我认为在将所有内容发送到“docker-user”后,将不再有流量需要排序,并且链的其余部分将完全未使用。但似乎每条规则捕获的流量数量相等,然后更多的流量继续到第 3 行。这是怎么回事?“forward”的前两行实际上在测试什么?
答案1
在移动设备上,评论太长
似乎您认为将数据包发送到自定义/新链意味着它不会从那里返回。这有点不正确。
iptables 中的规则会按顺序进行检查
当数据包与对该数据包的命运做出最终决定的规则匹配时,处理将停止(通常是 ACCEPT、DROP、REJECT 以及我可能忽略的其他规则)
当规则跳转到新的/自定义的链时:
- 进入该链
- 按顺序检查该链中的所有规则,直到对该数据包的命运做出最终决定
- 如果没有对数据包的命运做出最终决定:
返回上一个链
这就是 DOCKER-USER 链中发生的情况,只有少数数据包与 DOCKER-MAN 链中的规则或后续 REJECT 规则匹配,从而导致最终决策。几乎所有进入的数据包都不符合最终决策并返回到 FORWARD 链,在那里它们由下一条规则处理,它们将进入 DOCKER-ISOLATION-STAGE-1 链