![docker 究竟是如何绕过我的 nftables 的?](https://linux22.com/image/784217/docker%20%E7%A9%B6%E7%AB%9F%E6%98%AF%E5%A6%82%E4%BD%95%E7%BB%95%E8%BF%87%E6%88%91%E7%9A%84%20nftables%20%E7%9A%84%EF%BC%9F.png)
我的目标是阻止除 22、80、443 之外的所有非“lo”接口的端口。我不希望我的 Rasberry pi 的外部设备能够访问除 22、80、443 之外的任何其他端口。
我在端口 9123 上运行了一个 nc 服务器。我的 nftables 正确地阻止了 LAN 设备访问该端口。但是 - 我在 docker 中启动的任何服务似乎都没有被阻止 - 其他 LAN 设备可以访问 PI 上的 docker 服务器。我不太明白这是怎么回事。在第 107 行,我的默认策略是 DROP,接下来的一行在“lo”接口上添加了一个例外。这里到底发生了什么?我如何才能实现所需的行为(即)阻止 LAN 设备访问 pi 上除 22,80,443 之外的任何内容?谢谢
root@raspberrypi:/home/pi/tmp # nft list ruleset | awk '{printf "%d\t%s\n", NR, $0}'
1 table ip nat {
2 chain DOCKER {
3 iifname "docker0" counter packets 0 bytes 0 return
4 iifname "docker_gwbridge" counter packets 0 bytes 0 return
5 iifname "br-7a4b6e0a5c6f" counter packets 3840 bytes 115200 return
6 iifname != "br-7a4b6e0a5c6f" meta l4proto tcp tcp dport 8920 counter packets 0 bytes 0 dnat to 172.20.0.2:8920
7 iifname != "br-7a4b6e0a5c6f" meta l4proto tcp tcp dport 8096 counter packets 0 bytes 0 dnat to 172.20.0.2:8096
8 iifname != "docker0" meta l4proto tcp tcp dport 8080 counter packets 0 bytes 0 dnat to 172.17.0.2:8080
9 iifname != "br-7a4b6e0a5c6f" meta l4proto tcp tcp dport 445 counter packets 0 bytes 0 dnat to 172.20.0.3:445
10 iifname != "docker0" meta l4proto tcp tcp dport 3389 counter packets 0 bytes 0 dnat to 172.17.0.2:3389
11 iifname != "br-7a4b6e0a5c6f" meta l4proto tcp tcp dport 9125 counter packets 8306 bytes 531572 dnat to 172.20.0.5:80
12 iifname != "br-7a4b6e0a5c6f" meta l4proto tcp tcp dport 9123 counter packets 0 bytes 0 dnat to 172.20.0.6:80
13 iifname != "br-7a4b6e0a5c6f" meta l4proto tcp tcp dport 139 counter packets 0 bytes 0 dnat to 172.20.0.3:139
14 iifname != "br-7a4b6e0a5c6f" meta l4proto tcp tcp dport 9124 counter packets 0 bytes 0 dnat to 172.20.0.7:80
15 iifname != "br-7a4b6e0a5c6f" meta l4proto tcp tcp dport 32400 counter packets 0 bytes 0 dnat to 172.20.0.8:32400
16 }
17
18 chain POSTROUTING {
19 type nat hook postrouting priority srcnat; policy accept;
20 oifname != "docker0" ip saddr 172.17.0.0/16 counter packets 958 bytes 399977 masquerade
21 oifname != "docker_gwbridge" ip saddr 172.19.0.0/16 counter packets 0 bytes 0 masquerade
22 oifname != "br-7a4b6e0a5c6f" ip saddr 172.20.0.0/16 counter packets 184 bytes 12810 masquerade
23 oifname != "docker0" ip saddr 172.17.0.0/16 counter packets 0 bytes 0 masquerade
24 oifname != "br-7a4b6e0a5c6f" ip saddr 172.20.0.0/16 counter packets 8 bytes 502 masquerade
25 oifname != "docker_gwbridge" ip saddr 172.19.0.0/16 counter packets 0 bytes 0 masquerade
26 oifname != "docker0" ip saddr 172.17.0.0/16 counter packets 0 bytes 0 masquerade
27 oifname != "docker_gwbridge" ip saddr 172.19.0.0/16 counter packets 0 bytes 0 masquerade
28 oifname != "br-7a4b6e0a5c6f" ip saddr 172.20.0.0/16 counter packets 8 bytes 502 masquerade
29 oifname != "docker0" ip saddr 172.17.0.0/16 counter packets 45 bytes 3148 masquerade
30 oifname != "docker_gwbridge" ip saddr 172.19.0.0/16 counter packets 0 bytes 0 masquerade
31 oifname != "br-7a4b6e0a5c6f" ip saddr 172.20.0.0/16 counter packets 36 bytes 2324 masquerade
32 oifname != "docker0" ip saddr 172.17.0.0/16 counter packets 0 bytes 0 masquerade
33 oifname != "br-7a4b6e0a5c6f" ip saddr 172.20.0.0/16 counter packets 36 bytes 2324 masquerade
34 oifname != "docker_gwbridge" ip saddr 172.19.0.0/16 counter packets 0 bytes 0 masquerade
35 ip saddr 172.17.0.2 ip daddr 172.17.0.2 tcp dport 8080 counter packets 0 bytes 0 masquerade
36 ip saddr 172.20.0.2 ip daddr 172.20.0.2 tcp dport 8920 counter packets 0 bytes 0 masquerade
37 ip saddr 172.17.0.2 ip daddr 172.17.0.2 tcp dport 3389 counter packets 0 bytes 0 masquerade
38 ip saddr 172.20.0.4 ip daddr 172.20.0.4 tcp dport 32400 counter packets 0 bytes 0 masquerade
39 ip saddr 172.20.0.2 ip daddr 172.20.0.2 tcp dport 8096 counter packets 0 bytes 0 masquerade
40 ip saddr 172.20.0.5 ip daddr 172.20.0.5 tcp dport 80 counter packets 0 bytes 0 masquerade
41 ip saddr 172.20.0.6 ip daddr 172.20.0.6 tcp dport 445 counter packets 0 bytes 0 masquerade
42 ip saddr 172.20.0.7 ip daddr 172.20.0.7 tcp dport 80 counter packets 0 bytes 0 masquerade
43 ip saddr 172.20.0.8 ip daddr 172.20.0.8 tcp dport 80 counter packets 0 bytes 0 masquerade
44 ip saddr 172.20.0.6 ip daddr 172.20.0.6 tcp dport 139 counter packets 0 bytes 0 masquerade
45 ip saddr 172.20.0.2 ip daddr 172.20.0.2 tcp dport 80 counter packets 0 bytes 0 masquerade
46 ip saddr 172.17.0.2 ip daddr 172.17.0.2 tcp dport 8080 counter packets 0 bytes 0 masquerade
47 ip saddr 172.20.0.3 ip daddr 172.20.0.3 tcp dport 32400 counter packets 0 bytes 0 masquerade
48 ip saddr 172.17.0.2 ip daddr 172.17.0.2 tcp dport 3389 counter packets 0 bytes 0 masquerade
49 ip saddr 172.20.0.5 ip daddr 172.20.0.5 tcp dport 80 counter packets 0 bytes 0 masquerade
50 ip saddr 172.20.0.6 ip daddr 172.20.0.6 tcp dport 80 counter packets 0 bytes 0 masquerade
51 ip saddr 172.20.0.7 ip daddr 172.20.0.7 tcp dport 445 counter packets 0 bytes 0 masquerade
52 ip saddr 172.20.0.8 ip daddr 172.20.0.8 tcp dport 8920 counter packets 0 bytes 0 masquerade
53 ip saddr 172.20.0.7 ip daddr 172.20.0.7 tcp dport 139 counter packets 0 bytes 0 masquerade
54 ip saddr 172.20.0.8 ip daddr 172.20.0.8 tcp dport 8096 counter packets 0 bytes 0 masquerade
55 ip saddr 172.20.0.2 ip daddr 172.20.0.2 tcp dport 445 counter packets 0 bytes 0 masquerade
56 ip saddr 172.17.0.2 ip daddr 172.17.0.2 tcp dport 8080 counter packets 0 bytes 0 masquerade
57 ip saddr 172.20.0.3 ip daddr 172.20.0.3 tcp dport 80 counter packets 0 bytes 0 masquerade
58 ip saddr 172.17.0.2 ip daddr 172.17.0.2 tcp dport 3389 counter packets 0 bytes 0 masquerade
59 ip saddr 172.20.0.2 ip daddr 172.20.0.2 tcp dport 139 counter packets 0 bytes 0 masquerade
60 ip saddr 172.20.0.4 ip daddr 172.20.0.4 tcp dport 32400 counter packets 0 bytes 0 masquerade
61 ip saddr 172.20.0.6 ip daddr 172.20.0.6 tcp dport 80 counter packets 0 bytes 0 masquerade
62 ip saddr 172.20.0.8 ip daddr 172.20.0.8 tcp dport 80 counter packets 0 bytes 0 masquerade
63 ip saddr 172.20.0.9 ip daddr 172.20.0.9 tcp dport 8920 counter packets 0 bytes 0 masquerade
64 ip saddr 172.20.0.9 ip daddr 172.20.0.9 tcp dport 8096 counter packets 0 bytes 0 masquerade
65 ip saddr 172.20.0.2 ip daddr 172.20.0.2 tcp dport 80 counter packets 0 bytes 0 masquerade
66 ip saddr 172.17.0.2 ip daddr 172.17.0.2 tcp dport 8080 counter packets 0 bytes 0 masquerade
67 ip saddr 172.17.0.2 ip daddr 172.17.0.2 tcp dport 3389 counter packets 0 bytes 0 masquerade
68 ip saddr 172.20.0.3 ip daddr 172.20.0.3 tcp dport 80 counter packets 0 bytes 0 masquerade
69 ip saddr 172.20.0.4 ip daddr 172.20.0.4 tcp dport 80 counter packets 0 bytes 0 masquerade
70 ip saddr 172.20.0.5 ip daddr 172.20.0.5 tcp dport 8920 counter packets 0 bytes 0 masquerade
71 ip saddr 172.20.0.6 ip daddr 172.20.0.6 tcp dport 445 counter packets 0 bytes 0 masquerade
72 ip saddr 172.20.0.7 ip daddr 172.20.0.7 tcp dport 32400 counter packets 0 bytes 0 masquerade
73 ip saddr 172.20.0.5 ip daddr 172.20.0.5 tcp dport 8096 counter packets 0 bytes 0 masquerade
74 ip saddr 172.20.0.6 ip daddr 172.20.0.6 tcp dport 139 counter packets 0 bytes 0 masquerade
75 meta l4proto tcp ip saddr 172.20.0.2 ip daddr 172.20.0.2 tcp dport 8920 counter packets 0 bytes 0 masquerade
76 meta l4proto tcp ip saddr 172.20.0.2 ip daddr 172.20.0.2 tcp dport 8096 counter packets 0 bytes 0 masquerade
77 meta l4proto tcp ip saddr 172.17.0.2 ip daddr 172.17.0.2 tcp dport 8080 counter packets 0 bytes 0 masquerade
78 meta l4proto tcp ip saddr 172.20.0.3 ip daddr 172.20.0.3 tcp dport 445 counter packets 0 bytes 0 masquerade
79 meta l4proto tcp ip saddr 172.17.0.2 ip daddr 172.17.0.2 tcp dport 3389 counter packets 0 bytes 0 masquerade
80 meta l4proto tcp ip saddr 172.20.0.5 ip daddr 172.20.0.5 tcp dport 80 counter packets 0 bytes 0 masquerade
81 meta l4proto tcp ip saddr 172.20.0.6 ip daddr 172.20.0.6 tcp dport 80 counter packets 0 bytes 0 masquerade
82 meta l4proto tcp ip saddr 172.20.0.3 ip daddr 172.20.0.3 tcp dport 139 counter packets 0 bytes 0 masquerade
83 meta l4proto tcp ip saddr 172.20.0.7 ip daddr 172.20.0.7 tcp dport 80 counter packets 0 bytes 0 masquerade
84 meta l4proto tcp ip saddr 172.20.0.8 ip daddr 172.20.0.8 tcp dport 32400 counter packets 0 bytes 0 masquerade
85 }
86
87 chain PREROUTING {
88 type nat hook prerouting priority dstnat; policy accept;
89 fib daddr type local counter packets 86612 bytes 5842738 jump DOCKER
90 fib daddr type local counter packets 59086 bytes 4082250 jump DOCKER
91 fib daddr type local counter packets 58016 bytes 4020180 jump DOCKER
92 fib daddr type local counter packets 58010 bytes 4019512 jump DOCKER
93 fib daddr type local counter packets 21891 bytes 1551454 jump DOCKER
94 }
95
96 chain OUTPUT {
97 type nat hook output priority -100; policy accept;
98 ip daddr != 127.0.0.0/8 fib daddr type local counter packets 11 bytes 660 jump DOCKER
99 ip daddr != 127.0.0.0/8 fib daddr type local counter packets 10 bytes 600 jump DOCKER
100 ip daddr != 127.0.0.0/8 fib daddr type local counter packets 9 bytes 540 jump DOCKER
101 ip daddr != 127.0.0.0/8 fib daddr type local counter packets 8 bytes 480 jump DOCKER
102 ip daddr != 127.0.0.0/8 fib daddr type local counter packets 1 bytes 60 jump DOCKER
103 }
104 }
105 table ip filter {
106 chain INPUT {
107 type filter hook input priority -450; policy drop;
108 iifname "lo" counter packets 19231 bytes 156043045 accept
109 ip daddr 127.0.0.0/8 counter packets 0 bytes 0 reject
110 ct state established,related counter packets 67781 bytes 452733513 accept
111 icmp type echo-request accept
112 ct state new tcp dport 22 counter packets 119 bytes 7020 accept
113 ct state new tcp dport 443 counter packets 324 bytes 19343 accept
114 ct state new tcp dport 80 counter packets 17 bytes 916 accept
115 ip protocol icmp counter packets 0 bytes 0 accept
116 limit rate 5/minute counter packets 685 bytes 107167 log prefix "iptables denied: " level debug
117 tcp dport 9125 drop
118 counter packets 27066 bytes 4826608 drop
119 }
120
121 chain OUTPUT {
122 type filter hook output priority filter - 1; policy drop;
123 counter packets 133164 bytes 583633753 accept
124 }
125 }
答案1
正如人们所看到的Netfilter 和常规网络中的数据包流示意图如下:
nat 预路由链发生在路由决策之前。因此,当 Docker 使用 DNAT 将目标从初始网络命名空间(即主机)更改为其他网络命名空间(路由容器)时,流不再通过 filter/input,而是使用 filter/forward:不再遍历 ip 过滤器 INPUT 链。选择优先级 -450 不会改变任何东西:这是同一钩子内的优先级。预路由总是发生在输入(如图所示)无论选择何种优先级。在过滤器/输入中使用 -450 仅允许先遍历链,然后再遍历iptables'默认优先级0。
另外,选择ip filter INPUT
带有nftables就像 OP 的例子一样(因为优先级 -450 只能使用nftables) 可能与iptables-nft
的过滤器/INPUT 链的处理发生冲突,应避免。
INPUT 规则在以下几种情况下仍可使用:
- 与 Docker 无关时:docker 不会重定向不属于其容器的流量
- 当容器停止时(例如:应用程序崩溃且未自动重新启动),Docker 将删除相关规则:数据包不再路由/转发
- 可能取决于Docker的配置(关于
docker-proxy
和由Docker的全局参数控制的NAT发夹userland-proxy
)当一个容器是另一个容器的客户端时,在这种docker-proxy
情况下,流量不会被路由(因为它经过docker-proxy
一个代理)从而到达输入钩子。
我也在 UL SE 问答中回答了如何使用nftables和 Docker 一样,它自己也使用iptables和br_netfilter内核模块也会影响nftables即使nftables没有足够的工具来应对: