如何将“匿名”网络命名空间内的 veth 设备连接到外部?

Omn*_*ous 8 networking network-namespaces

我有一个进程调用unshare创建一个新的网络命名空间,里面只有它自己。当它调用execve启动 bash 时,ip 命令显示我只有一个lo设备。如果我还创建了一个用户命名空间并将我的进程安排为命名空间内的 root,我可以使用该ip命令启动该设备并且它可以工作。

我还可以使用该ip命令veth在此命名空间中创建设备。但它没有出现在ip netns listveth设备中,并且新设备也没有出现在根级命名空间中(正如我所期望的)。如何将veth根级命名空间中的设备连接到veth进程命名空间中的新设备?该ip命令似乎要求命名空间具有由ip命令分配的名称,而我的则不需要,因为我没有使用ip netns add它来创建它。

也许我可以通过编写自己的程序来使用 netlink 设备并进行设置。但我真的不想这样做。有没有办法通过命令行来做到这一点?

必须有办法做到这一点,因为 docker 容器也有自己的网络命名空间,而且该命名空间也是未命名的。然而,veth它内部有一个设备连接到veth它外部的设备。

我的目标是动态创建进程隔离上下文,理想情况下不需要成为容器外的 root。为此,我将创建一个 PID 命名空间、一个 UID 命名空间、一个网络命名空间、一个 IPC 命名空间和挂载命名空间。我也可以创建一个 cgroup 命名空间,但这些都是新的,我需要能够在当前支持的 SLES、RHEL 和 Ubuntu LTS 版本上运行。

我一直在处理这个命名空间,目前我的 User、PID 和 mount 命名空间工作令人满意。

/proc/pid/ns/net如果必须,我可以挂载,但我更愿意从用户命名空间内部执行此操作,因此(再次)我不必在命名空间之外成为 root。大多数情况下,一旦命名空间中的所有进程都消失了,我希望一切都消失。完成后在文件系统上清理一堆状态会不太理想。尽管在容器首次分配时临时创建它然后立即删除它比在容器退出时必须清理它要好得多。

不,我不能使用泊坞窗LXCRKT,或任何其他现有的解决方案,使得我可以依靠比沼泽标准系统工具(像其他任何IP),系统库一样的glibc和Linux系统调用。

seb*_*sth 6

ip link有一个命名空间选项,除了网络命名空间名称之外,它还可以使用PID来引用进程的命名空间。如果进程之间共享PID 命名空间,则可以通过任何一种方式移动设备;当您认为PID 1“外部”时,从内部可能是最简单的。使用单独的PID 命名空间,您需要从外部 (PID) 命名空间移动到内部命名空间。

例如,从网络命名空间内部,您可以创建一个到PID 1命名空间的veth 设备对

ip link add veth0 type veth peer name veth0 netns 1
Run Code Online (Sandbox Code Playgroud)

命名空间在 Linux 中的工作原理

每个进程在/proc/<pid>/ns/. 此外,ip netns/run/netns/. 这些文件与setns系统调用一起使用,以将正在运行的线程的命名空间更改为此类文件指向的命名空间。

从 shell 您可以使用nsenter程序进入另一个命名空间,在参数中提供命名空间文件(路径)。

LWN.net 上的Namespaces in operation文章系列很好地概述了 Linux 命名空间

设置命名空间

当您设置多个命名空间(mount、pid、user等)时,请在更改mountpid命名空间之前尽早设置网络命名空间。如果你没有共享的mountpid命名空间,你就没有任何方法指向外部的网络命名空间,因为你看不到引用外部网络命名空间的文件。

如果您需要比命令行实用程序提供的更多灵活性,则需要使用系统调用直接从您的程序管理名称空间。有关文档,请参阅相关手册页:man 2 setnsman 2 unshareman 7 namespaces