使用 ip netns (iproute2) 进行命名空间管理

使用 ip netns (iproute2) 进行命名空间管理

我想知道在哪里查找应用于自定义命名空间的更改。假设我有一个名称空间“ns1”,其中包含虚拟接口“vpeer”和“lo”,我想通过 dnsmasq 或 hostapd 修改接口“vpeer”的配置,那么我知道我可以使用例如

$ ip netns exec ns1 bash
$ dnsmasq --interface=vpeer-ns1 --dhcp-range=192.168.0.100,192.168.0.200,255.255.255.0

netns 正在为我安装它并管理所有任务,从而完成其余的工作,对此我表示感谢。但是,在全局命名空间中,我可以监视相应文件中所做的更改或直接将它们应用到文件中。例如在/etc/dnsmasq.conf或者/etc/hostapd/hostapd.conf

所以我的问题是,如何复制某个 netns 命名空间中的默认命名空间行为。我真的需要知道我已经做了什么以及“ns1”中接口的当前配置是什么。尤其是因为大多数教程都会解释这样的过程。这ip netns 手册页说配置文件位于

$ /etc/netns/ns1/

但在创建名称空间“ns1”后,甚至目录 /etc/netns 也不存在。新的命名空间仅在 /var/run/netns/ns1 中表示。该文件始终为空 - 即使在应用上面的 dnsmasq 命令之后 - 并且 nano 显示为空文件,但在文件关闭后给我一些奇怪的错误

ns1: Argument is invalid.

所以我切换到名称空间“ns1”并再次尝试。相同的结果。所以我把新命名空间中的每个设备都关闭了

$ ip netns exec ns1 ip link set dev lo down
$ ip netns exec ns1 ip link set dev vpeer down

再次,同样的结果。

那么我如何访问配置文件对于给定的命名空间,因为据我所知,应用程序根本不知道非默认命名空间?先感谢您。

答案1

您有两个问题合而为一:

  • 里面的空文件是什么/var/run/netns/
  • 如何使用/etc/netns/甚至不存在的东西?

里面的空文件是什么/var/run/netns/

一些了解命名空间是需要的。我在这里无法详细解释。可以说,命名空间一旦创建就会(对某些内核资源(例如网络)进行分区),只要有东西正在使用它,它就会存在。大多数情况下有两件事会使用它:进程或特殊伪文件系统中的安装点nsfs。一旦他们停止使用它或消失,命名空间也会消失。

ip netns(专门从事网络命名空间)选择通过安装对网络命名空间的引用来保留网络命名空间。这些引用都可以/proc/<pid>/net/作为符号链接使用。例子:

$ ls -l /proc/$$/ns/net
lrwxrwxrwx. 1 user user 0 Sep 25 01:05 /proc/19120/ns/net -> net:[4026531992]
$ stat -L -f -c %T /proc/19120/ns/net # filesystem type. "df" on this would be confused and point to the wrong mountpoint anyway.
nsfs
$ stat -L -c %i /proc/19120/ns/net # inode
4026531992

ip netns add只需将它们绑定安装到/var/run/netns/<NAME>.请注意,虽然您通常在目录上绑定安装目录,但也可以在文件上绑定安装文件。另请注意,该文件是文件系统中的伪文件nsfs。它不是为阅读而设计的,也不可能是。它主要用于通过打开(但不是读取或写入)或安装它来作为参考传递:

# strace -e unshare,mount  ip netns add ns1
mount("", "/var/run/netns", 0x5625f6ca80e3, MS_REC|MS_SHARED, NULL) = 0
unshare(CLONE_NEWNET)                   = 0
mount("/proc/self/ns/net", "/var/run/netns/ns1", 0x5625f6ca80e3, MS_BIND, NULL) = 0
+++ exited with 0 +++
# ip netns list
ns1
# ls -l /var/run/netns/ns1
-r--r--r--. 1 root root 0 Sep 25 01:08 /var/run/netns/ns1
# cat /var/run/netns/ns1
cat: /var/run/netns/ns1: Invalid argument
# stat -f -c %T /var/run/netns/ns1
nsfs
# stat -c %i /var/run/netns/ns1
4026532824
# ip netns exec ns1 sleep 99 &
[1] 19620
# ls -l /proc/19620/ns/net
lrwxrwxrwx. 1 root root 0 Sep 25 01:23 /proc/19620/ns/net -> net:[4026532824]

因此sleep 99,网络命名空间是来自挂载点的网络命名空间/var/run/netns/ns1。例如,使用此方法,可以拥有一个带有桥的网络命名空间,该网桥通过veth接口链接到其他命名空间并且不运行任何进程,因为不需要任何进程。

您可以手动删除ip netns使用以下命令创建的命名空间:

# umount /var/run/netns/ns1 
# rm /var/run/netns/ns1
# ip netns list
#

当然,只有当最后一个使用它的引用(例如:进程)也消失时,网络名称空间才会真正消失。如果之前的 sleep 命令仍在运行,您甚至可以将其放回去:

# touch /var/run/netns/ns1
# mount --bind /proc/19620/ns/net /var/run/netns/ns1
# ip netns
ns1

这可以用来“复制”完整容器的网络命名空间部分,您只需要知道主机端的一些 pid (例如:lxc-info -Hp -n containerdocker inspect --format '{{.State.Pid}}' container)并挂载其网络命名空间。可以方便地运行容器内不可用的调试命令(tcpdump...)。

上面的所有内容都是短暂的,例如,它会在重新启动后消失。

如何使用/etc/netns/根本不存在的东西?

ip netns联机帮助页告诉(粗体强调我的):

对于了解网络命名空间的应用程序/etc/netns/,约定是首先在NAME/中查找全局网络配置文件, 然后在/etc/.例如,如果您想要使用不同版本的/etc/resolv.conf网络名称空间来隔离您的 VPN,您可以将其命名为/etc/netns/myvpn/resolv.conf.

现在,dnsmasq“意识到”网络命名空间了吗?如果是(根据ip netns的定义),它将以/etc/netns/某种方式进行检查。没有提到“netns”它的联机帮助页。当前 Debian 的(类似于 Raspberry 的)源代码在任何地方都不包含该词netns:它不支持网络名称空间。

这就是为什么ip netns联机帮助页的以下句子告诉我们:

ip netns exec自动处理此配置、文件约定对于不知道网络命名空间的应用程序,通过创建安装命名空间并将所有每个网络命名空间配置文件绑定安装到/etc.

这并没有真正解释,但与前面的句子一起,这确实意味着ip netns exec将绑定安装,如果源和目标都存在/etc/netns/<NAME>/whatever/etc/whatever/etc/netns以及内部选择的网络命名空间名称,其中将包含配置必须首先手动创建,并且实际的配置内容可能会复制到内部并进行编辑ip netns exec如果找到,将使用它们,但不会创建它们。

例子:

# mkdir -p /etc/netns/ns1
# echo something > /etc/netns/ns1/whatever
# : > /etc/whatever
# ip netns add ns1
# cat /etc/whatever
# ip netns exec ns1 cat /etc/whatever
something

背后到底发生了什么:

# strace -e open,unshare,setns,mount,umount2 ip netns exec ns1 cat /etc/whatever 2>&1 |egrep '^(open.*/etc/netns|unshare|setns|mount|umount|something)'
setns(5, CLONE_NEWNET)                  = 0
unshare(CLONE_NEWNS)                    = 0
mount("", "/", 0x55947eb550e3, MS_REC|MS_SLAVE, NULL) = 0
umount2("/sys", MNT_DETACH)             = 0
mount("ns1", "/sys", "sysfs", 0, NULL)  = 0
open("/etc/netns/ns1", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 5
mount("/etc/netns/ns1/whatever", "/etc/whatever", 0x55947eb550e3, MS_BIND, NULL) = 0
something

当然,这对于内部目录/etc/netns/ns1而不是文件来说是一样的:整个目录将直接出现在/etc/屏蔽主机的同名目录中,只有当它存在时。

因此,如果 dnsmasq 的默认配置(除非另有说明)是,您可以为as/etc/dnsmasq.conf创建一个备用配置,并使其显示为to ,ns1/etc/netns/ns1/dnsmasq.confip netns exec/etc/dnsmasq.confdnsmasq如果/etc/dnsmasq.conf即使它是空的,也已经有一个文件。因为它/etc不是短暂的,并且每当您重新创建相同的网络命名空间名称时都会被重用。hostapd整个目录相同/etc/hostapd/,可以复制/etc/netns/ns1/hostapd/它的文件,然后在里面修改。小心指向外部的符号链接。您现在可以像往常一样在里面运行命令ip netns exec ns1:它们将使用新的配置文件。

相关内容