![根网络命名空间作为另外 2 个网络命名空间之间的传输](https://linux22.com/image/219733/%E6%A0%B9%E7%BD%91%E7%BB%9C%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%E4%BD%9C%E4%B8%BA%E5%8F%A6%E5%A4%96%202%20%E4%B8%AA%E7%BD%91%E7%BB%9C%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%E4%B9%8B%E9%97%B4%E7%9A%84%E4%BC%A0%E8%BE%93.png)
我正在尝试使用图中所示的 veth 对通过根命名空间连接的两个网络命名空间之间进行通信。我无法执行从 netns A 到 netns B 的 ping。此外,我可以从根命名空间 ping 到 netns A (VA IP) 和 B (VB IP)。
+-------+ +-------+
| A | | B |
+-------+ +-------+
| VA | VB
| |
| RA | RB
+-------------------------+
| |
| Root namespace |
| |
+-------------------------+
ip netns add A
ip netns add B
ip link add VA type veth peer name RA
ip link add VB type veth peer name RB
ip link set VA netns A
ip link set VB netns B
ip addr add 192.168.101.1/24 dev RA
ip addr add 192.168.102.1/24 dev RB
ip link set RA up
ip link set RB up
ip netns exec A ip addr add 192.168.101.2/24 dev VA
ip netns exec B ip addr add 192.168.102.2/24 dev VB
ip netns exec A ip link set VA up
ip netns exec B ip link set VB up
ip netns exec A ip route add default via 192.168.101.1
ip netns exec B ip route add default via 192.168.102.1
我已尝试启用 IP 转发,并且没有 IP 表规则阻止流量。当我不使用根命名空间而是使用另一个名为“transit”的命名空间并将其连接起来时,效果相同,如下所示。
+-------+ VA RA +-------+ RB VB +-------+
| A |--------|transit|---------| B |
+-------+ +-------+ +-------+
+-------------------------+
| |
| Root namespace |
| |
+-------------------------+
这里我成功地在命名空间 A 和 B 之间执行 ping 操作。
为什么流量在根命名空间处被丢弃,而在使用第三个中转命名空间时却没有?
docker 安装了一些 iptable 规则,但我没有看到任何冲突。
rahul@inception:~$ sudo iptables -L -n -v
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy DROP 2 packets, 168 bytes)
pkts bytes target prot opt in out source destination
2 168 DOCKER-USER all -- * * 0.0.0.0/0 0.0.0.0/0
2 168 DOCKER-ISOLATION-STAGE-1 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 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
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
pkts bytes target prot opt in out source destination
0 0 DOCKER-ISOLATION-STAGE-2 all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
2 168 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
0 0 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
2 168 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
nft 列表格式
rahul@inception:~$ sudo nft list ruleset
table ip nat {
chain DOCKER {
iifname "docker0" counter packets 0 bytes 0 return
}
chain POSTROUTING {
type nat hook postrouting priority srcnat; policy accept;
oifname != "docker0" ip saddr 172.17.0.0/16 counter packets 1 bytes 90 masquerade
}
chain PREROUTING {
type nat hook prerouting priority dstnat; policy accept;
fib daddr type local counter packets 148 bytes 11544 jump DOCKER
}
chain OUTPUT {
type nat hook output priority -100; policy accept;
ip daddr != 127.0.0.0/8 fib daddr type local counter packets 3 bytes 258 jump DOCKER
}
}
table ip filter {
chain DOCKER {
}
chain DOCKER-ISOLATION-STAGE-1 {
iifname "docker0" oifname != "docker0" counter packets 0 bytes 0 jump DOCKER-ISOLATION-STAGE-2
counter packets 2 bytes 168 return
}
chain DOCKER-ISOLATION-STAGE-2 {
oifname "docker0" counter packets 0 bytes 0 drop
counter packets 0 bytes 0 return
}
chain FORWARD {
type filter hook forward priority filter; policy drop;
counter packets 2 bytes 168 jump DOCKER-USER
counter packets 2 bytes 168 jump DOCKER-ISOLATION-STAGE-1
oifname "docker0" ct state related,established counter packets 0 bytes 0 accept
oifname "docker0" counter packets 0 bytes 0 jump DOCKER
iifname "docker0" oifname != "docker0" counter packets 0 bytes 0 accept
iifname "docker0" oifname "docker0" counter packets 0 bytes 0 accept
}
chain DOCKER-USER {
counter packets 2 bytes 168 return
}
}
ip路由
rahul@inception:~$ ip route
default via 192.168.0.1 dev wlo1 proto dhcp metric 600
169.254.0.0/16 dev wlo1 scope link metric 1000
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
192.168.0.0/24 dev wlo1 proto kernel scope link src 192.168.0.101 metric 600
192.168.101.0/24 dev RA proto kernel scope link src 192.168.101.1
192.168.102.0/24 dev RB proto kernel scope link src 192.168.102.1
使用 TCPDUMP 我发现数据包正在到达根命名空间。是否有任何我可以学习并可用于查看数据包在命名空间内遍历的位置的调试工具(例如 strace 或 ftrace)?
答案1
Docker 改变了默认转发策略为 DROP:
Docker 还将 FORWARD 链的策略设置为 DROP。如果您的 Docker 主机还充当路由器,这将导致该路由器不再转发任何流量。
就像OP的情况一样:
Chain FORWARD (policy DROP 2 packets, 168 bytes)
文档还告诉我们:
如果您希望系统继续充当路由器,您可以
ACCEPT
向链添加明确的规则DOCKER-USER
以允许它:
解决方法是在链中启用此类流量DOCKER-USER
(通过插入该链而不是附加,因为有最终RETURN
目标)。
因此,在不允许更多实验的情况下不受阻碍地进行实验的最小解决办法是:
iptables -I DOCKER-USER 1 -i RA -o RB -j ACCEPT
iptables -I DOCKER-USER 2 -i RB -o RA -j ACCEPT