我知道你可以通过做来显示界面ip a show
。那只显示主机可以看到的接口,但容器配置的虚拟接口不会出现在这个列表中。我也尝试过使用ip netns
,它们也没有出现。我应该重新编译另一个版本iproute2
吗?在/proc/net/fb_trie
中,您可以看到本地/广播地址,我假设,作为转发数据库的用途。
我在哪里可以找到这些信息或列出所有接口(包括容器)的命令?
要对此进行测试,请启动一个容器。就我而言,它是 snap 上的 lxc 容器。做一个ip a
或ip l
。它将显示主机的视图,但不显示容器配置的界面。我正在通过grepping ,因为容器只是 cgrouped 进程,但除了和 arp 条目procfs
之外我没有得到任何东西。fib_trie
我认为这可能是由于 netns 命名空间混淆,但ip netns
也没有显示任何内容。
您可以使用conntrack -L
显示所有已建立的传入和传出连接,因为 lxd 需要连接跟踪数据包的转发,但我想列出系统上配置的所有 IP 地址,就像我能做到的那样告诉使用netstat
or lsof
。
一个接口,在给定的时间,属于一个网络命名空间并且只属于一个。init(初始)网络命名空间,除了继承被破坏的网络命名空间的物理接口外,对其他网络命名空间没有特殊的能力:它不能直接看到它们的接口。只要你还在 init 的 pid 和 mount 命名空间中,你仍然可以通过使用不同的可用信息找到网络命名空间,
/proc
并最终通过输入这些网络命名空间来显示它们的接口。我将在 shell 中提供示例。
枚举网络命名空间
为此,您必须知道这些名称空间是如何存在的:只要资源保持它们。这里的资源可以是进程(实际上是进程的线程)、挂载点或打开的文件描述符(fd)。这些资源都被引用
/proc/
并指向伪文件系统中nsfs
枚举所有命名空间的抽象伪文件。这个文件唯一有意义的信息是它的inode,代表网络命名空间,但是inode不能单独操作,它必须是文件。这就是为什么稍后我们不能只保留 inode值stat -c %i /proc/some/file
(由nsenter
进程(实际上是线程)
最常见的情况:对于普通容器。每个线程的网络命名空间都可以通过引用获知
/proc/pid/ns/net
:仅stat
它们并枚举所有唯一的命名空间。这是在找不到临时进程2>/dev/null
时隐藏。stat
这可以通过
lsns
处理命名空间的专用命令更快地完成,但似乎只处理进程(不是挂载点,也不是打开 fd,如后面所示):(必须重新格式化以备后用
lsns -n -u -t net -o NS,PATH | while read inode path; do printf '%20u %s\n' $inode "$path"; done
)挂载点
这些主要由
ip netns add
通过安装它们来创建永久网络命名空间的命令使用,从而避免它们在没有进程或 fd 资源保持它们时消失,然后还允许例如在网络命名空间中运行路由器、防火墙或网桥任何关联的过程。挂载的命名空间(处理挂载和可能的 pid 命名空间可能更复杂,但我们只对网络命名空间感兴趣)看起来像 中的任何其他挂载点
/proc/mounts
,文件系统类型为nsfs
。在 shell 中没有简单的方法来区分网络命名空间和其他类型的命名空间,但是由于来自同一文件系统(此处)的两个伪文件nsfs
不会共享相同的 inode,只需将它们全部选中并稍后在界面中忽略错误尝试使用非网络命名空间引用作为网络命名空间时的步骤。抱歉,下面我不会正确处理带有特殊字符的挂载点,包括空格,因为它们已经在/proc/mounts
's 的输出中转义(在任何其他语言中都会更容易),所以我不会费心使用 null终止的行。打开文件描述符
这些可能比挂载点更罕见,除了在命名空间创建时临时,但可能由一些处理多个命名空间的专门应用程序持有和使用,包括可能的一些容器化技术。
我无法设计出比在 every 中搜索所有可用 fd 更好的方法
/proc/pid/fd/
,使用 stat 来验证它指向一个nsfs
命名空间,并且现在再次不在乎它是否真的是一个网络命名空间。我确信有一个更优化的循环,但这个循环至少不会到处乱跑,也不会假设任何最大进程限制。现在从以前的结果中删除所有重复的网络命名空间引用。例如,通过在 3 个先前结果的组合输出上使用此过滤器(尤其是来自打开的文件描述符部分):
在每个命名空间中枚举接口
现在我们有了对所有现有网络命名空间的引用(以及一些我们将忽略的非网络命名空间),只需使用引用输入它们中的每一个并显示接口。
将先前命令的输出作为此循环的输入以枚举接口(并根据 OP 的问题,选择显示它们的地址),同时忽略由非网络命名空间引起的错误,如前所述:
初始化网络的 inode 可以打印 pid 1 作为参考:
使用正在运行的 LXC 容器的示例(真实但经过编辑)输出,使用
ip netns add ...
未连接的网桥接口创建的空“已安装”网络名称空间,具有其他接口的网络名称空间,由不在此网络名称空间中但保持打开dummy0
的进程保持活动状态fd 就可以了,创建:和一个正在运行的 Firefox,它将它的每个“Web 内容”线程隔离在一个未连接的网络命名空间(所有那些关闭的
lo
接口)中:ip netns list
将仅列出通过该ip-netns(8)
实用程序配置的网络名称空间。包中的
lsns(1)
程序util-linux
也有很大的缺陷:它只会列出那些可以通过/proc/<pid>/ns/*
文件访问的命名空间,忽略所有每个线程的命名空间以及那些通过绑定挂载或打开的文件描述符保持活动状态的命名空间。以下演示脚本试图做得更好:它将通过文件查找绑定挂载
/proc/<pid>/task/<tid>/mountinfo
,并通过文件查找打开的 fds/proc/<pid>/task/<tid>/fd
。对于每个命名空间,它将打印一个可访问的路径:
然后,您可以使用该路径
nsenter(1)
,例如。该脚本可以很容易地更改为自己执行此操作,或显示其他信息,例如使用命名空间的整个进程列表。
如果路径不可访问,它将跟随父/挂载 ID 和
/proc/<pid>/mountinfo
找到它的文件。转义的换行符、制表符和空格将保持原样:由于它必须读取所有这些
/proc/*/task/*
文件,因此在使用大量线程程序的任何机器上这可能会变慢;不幸的是,我找不到任何快速的方法来检查两个线程/任务是否共享相同的命名空间:kcmp(2)
只会告诉它们是否共享相同的地址空间、文件描述符表等;没有任何与命名空间相关的东西。lsnsx.pl
: