我正在使用全新安装的 Ubuntu 服务器 24.04.1 LTS。我以 root 身份运行以下命令来设置网络并进行一些实验:
apt install netcat-traditional
ip netns add ns1
ip netns add ns2
ip link add my_veth1 type veth peer name my_veth2
ip link set my_veth1 up netns ns1
ip link set my_veth2 up netns ns2
ip -n ns1 address add 1.2.3.4 dev my_veth1
ip -n ns1 route add 2.3.4.0/24 dev my_veth1
ip netns exec ns2 nc -u -l -p 8080
然后我从另一个终端运行它:
ip netns exec ns1 nc -u 2.3.4.5 8080 <<< 'Hello world from network namespace ns1'
UDP 是一种无连接协议。如果我的理解正确,这应该意味着来自网络命名空间 ns2 的 netcat UDP 服务器应该能够打印来自 ns1 的客户端发送的消息,无论服务器是否可以到达客户端,因此理论上我不必在 中配置路由ns2
或在 中配置 ip 地址my_veth2
。但是,除非同时配置了 ip 地址和路由表条目,否则第一个终端中不会打印任何消息。为什么?
- 我尝试添加 IP 地址
2.3.4.5
,my_veth2
但没有作用。 - 我尝试创建一个新的路由表条目
ns2
来将所有流量重定向1.2.3.0/24
到,my_veth2
但这也不起作用。 2.3.4.5
仅当将 IP 地址添加到my_veth2
并在 ns2 中创建新的路由表条目以将所有流量从 重定向1.2.3.0/24
到时,才会打印该消息my_veth2
。这是为什么?
编辑:禁用 rp_filter 似乎不起作用:
ip netns exec ns1 dd of=/proc/sys/net/ipv4/conf/all/rp_filter <<< '0'
ip netns exec ns2 dd of=/proc/sys/net/ipv4/conf/all/rp_filter <<< '0'
ip netns exec ns1 dd of=/proc/sys/net/ipv4/conf/my_veth1/rp_filter <<< '0'
ip netns exec ns2 dd of=/proc/sys/net/ipv4/conf/my_veth2/rp_filter <<< '0'
编辑2:安装并运行 tcpdump 我了解到有一些发送的 ARP 请求没有得到响应:
$ ip netns exec ns1 tcpdump -l -i my_veth1
23:38:14.402259 ARP, Request who-has 2.3.4.5 tell 1.2.3.4, length 28
23:38:14.402259 ARP, Request who-has 2.3.4.5 tell 1.2.3.4, length 28
23:38:14.402259 ARP, Request who-has 2.3.4.5 tell 1.2.3.4, length 28
...
ns2 my_veth2 给出相同的输出
因此我尝试手动创建 ARP 表条目...
ip -n ns1 neighbour add 2.3.4.5 dev my_veth1 lladdr $(ip netns exec ns2 cat /sys/class/net/my_veth2/address)
现在显然 UDP 数据包正在被发送
$ ip netns exec ns1 tcpdump -l -i my_veth1
00:24:15.164245 IP 1.2.3.4.36170 > 2.3.4.5.8080: UDP, length 39
ns2 my_veth2 给出相同的输出
但是,第一个运行 UDP netcat 服务器的终端仍然没有输出任何内容。为什么?
编辑 3:完成上述所有操作后,我尝试为以下设备分配一个 IP 地址my_veth2
:
ip -n ns2 address add 2.3.4.5 dev my_veth2
现在,当我发送 UDP 数据包时,在以监听模式运行 netcat 的终端中出现此错误:
no connection : Network is unreachable
为什么?我的意思是,当然网络无法连接,但这不应该阻止服务器接收和显示 UDP 数据包。事实上,只有在收到 UDP 数据包时才会显示该错误。所以即使它知道它无法应答,它也应该能够接收和显示消息,对吧?
您最初仅在 ns1 上创建一个 IP 地址“IP1”,并在 ns2 上创建一条到虚构的(不存在的)IP 地址“IP2”的路由。
尝试从 ns1 发送到 IP2 也会失败,因为它需要一个(链路层)MAC 地址来传送数据包。因此您会看到 ARP 请求。ns2 不会响应 IP2 的 ARP 请求,因为它没有 IP2。
在 ns1 上手动添加 IP2 的 ARP 条目可以解决此链路层问题。在 ns2 上现在可以观察到来自 ns1 的数据包。
但是 netcat 仍然不会显示任何内容,因为它只期望 0.0.0.0 上的数据包 - 这意味着 ns2 中配置的任何 IP 地址。只有 IP2 未在 ns2 中配置。因此,即使数据包在链路层被接收,也不会在网络层 (IP) 上进行处理 - 根本没有与数据包目的地匹配的 IP 地址。
仅当 IP2 被添加为 ns2 的 IP 后,ns2 中的网络层才会对其负责并将有效负载传递给应用程序 (nc)。
回答我自己的第三次编辑......
我不知道在这种情况下决定拒绝 UDP 数据包的真正原因,但我能想到这样做的几个原因: