我正在寻找输入,以下与网络命名空间到期相关的观察是否是预期的,或者应该报告为错误?
- 当某个进程打开时,
/proc/<pid>/net/dev
它可以阻止/延迟另一个进程的命名空间的到期,直到它关闭该文件。它不需要成为该名称空间的一部分即可这样做。
这似乎是非常令人惊讶的行为。它允许本地用户访问适当的proc
文件,以延迟/防止网络命名空间的 veth 接口被破坏。有缺陷的监控工具打开文件/proc
而不关闭它们也可能导致这种情况。
复制器
(在 Debian Buster - Linux 5.4.0-0.bpo.4-amd64 上)
1)创建网络命名空间:
$ unshare -n
$ echo $BASHPID
18807
2)创建veth并将一端移至上面创建的网络命名空间中
$ ip link add dev veth18807 type veth peer name eth18807
$ ip link set eth18807 netns 18807
$ ip addr | grep veth
14: veth18807@if13: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
3)tail -f /proc/18807/net/dev
在单独的终端中启动
$ tail -f /proc/18807/net/dev
...
tail: /proc/18807/net/dev: file truncated
...leave hanging...
4) 在1)中,退出命名空间,列出接口:
$ ip addr | grep veth
14: veth18807@if13: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
之前创建的veth
仍然存在。但是,步骤 1) 中创建的网络命名空间没有明显的痕迹。lsns
不显示它,没有进程在其/ns
目录中拥有它,等等。
一旦tail -f
中断,界面立即消失ip addr
。不需要是尾巴,只要打开它就open()
足够了。
我怀疑从技术上讲这可能是有意义的,因为打开../net/dev
可能需要引用网络名称空间。只是令人非常惊讶的是,能够以这种方式保持命名空间的活力。
作为解决方法,显式删除veth
使用之前创建的ip link del
作品。但是,我确实想知道这是否仍会保留命名空间。
火狱示例
此次调查是由于 firejail 消息抱怨“已在使用”的 IP 地址而引发的。在陷入兔子洞之后,最终似乎使用静态IP,可以按如下方式激发它:
1)开始监狱
$ /usr/local/bin/firejail --net=docker0 --ip=172.30.0.30 --noprofile
Parent pid 20890, child pid 20891
Interface MAC IP Mask Status
lo 127.0.0.1 255.0.0.0 UP
eth0 e2:87:2e:06:07:5b 172.30.0.30 255.255.0.0 UP
Default gateway 172.30.0.1
Child process initialized in 1491.22 ms
2)在单独的终端中打开net/dev
子项:
$ tail -F /proc/20891/net/dev
3) 退出上面firejail
并再次使用相同的参数重新启动。
$ /usr/local/bin/firejail --net=docker0 --ip=172.30.0.30 --noprofile
Error: IP address 172.30.0.30 is already in use
上述消息是因为 veth 继续响应firejail
该 IP 的 ARP 检查。
码头工人
我无法使用 docker 重现上述 Firejail 场景 - 容器停止后界面消失。也许 Docker 实际上实现了ip link del
解决方法(?)。
参考
在 linuxcontainers 上也报告了类似的观察结果,并且与内核错误相关。
这通常表明容器的网络命名空间从未过期,这通常表明内核存在问题。当使用网络命名空间的最后一个进程消失时,该命名空间将被销毁,这会导致所有虚拟接口被销毁,并且物理接口将移回主机网络命名空间。