【问题标题】:How to get interface name from IPv4 ip address using only fs and bash in Linux?如何在 Linux 中仅使用 fs 和 bash 从 IPv4 ip 地址获取接口名称?
【发布时间】:2017-03-30 17:15:19
【问题描述】:

如何仅使用 /proc、/dev、/sys 和 bash 等文件系统从 IPv4 ip 地址获取接口名称?如果不使用命令(如 ip、ifconfig 等),这可能吗?我也无法使用任何软件包或安装任何工具。

编辑: 这样做的原因是我试图从 Docker 容器中获取主机的接口名称和 IP 地址。该容器使用主机的根目录挂载,并且可以访问主机的文件系统。但是,由于容器位于单独的命名空间中,因此 ip 命令(以及其他类似的命令,例如 ifconfig)只会返回容器的网络。因此,我相信获取主机接口名称和 IP 地址的唯一方法是通过主机的根目录(/hostroot/proc、/hostroot/sys 等)。请注意,在启动容器时我不能有 --net=host 标志(它告诉容器使用主机的网络命名空间)。

我尝试从 /proc/net/fib_trie 文件中查找我所有的网络接口 IP 地址 (IPv4)。我在https://regexit.com/3-ways-to-get-your-ip-on-a-linux-system/ 阅读,基本上说我可以做 cat /proc/net/fib_trie | grep -B 1 "32 host LOCAL" 查找 IP 地址。我还在https://stackoverflow.com/a/42082822 中看到,我们可以通过匹配字符串“32 host”的模式来过滤fib_trie,以获取本地网络接口地址。从上述方法(使用 /proc/net/fib_trie)获取 IP 地址后,我尝试将这些 IP 地址与 /proc/net/route 中的“目标”IP 地址匹配以获取网络接口名称。但是,我的 /proc/net/route 包含某些接口(例如 enp0s3)的多个条目。例如,有两个具有不同 IP 地址的 enp0s3 条目(“Destination 列”)。此外,路由文件中的网络接口的 ip 确实与 ip 命令指示的值接近,但并不完全一致。

从fib_trie获取IP地址后,有没有更好的获取网络接口名称的方法?

我需要的输出是所有主机的网络接口名称和对应的 IPv4 IP 地址。

【问题讨论】:

  • 如果您不使用任何命令,您打算如何获取您根本没有的任何信息?为什么这是一个约束?你到底在问什么?
  • 你能告诉我们你用你正在尝试的实际命令和你需要的输出尝试了什么吗?
  • 添加了更多信息以发布。谢谢

标签: linux bash networking procfs sysfs


【解决方案1】:

我认为你那里有足够的信息。 /proc/net/route 文件并没有真正列出地址。它应该告诉你如何路由数据包。但是您可以从中收集有关接口的信息。在我的系统上(ubuntu 14 的接口名称格式不同,但其他方面应该是相似的),它显示如下:

Iface   Destination Gateway     Flags   RefCnt  Use Metric  Mask        MTU Window  IRTT
eth0    00000000    0100A8C0    0003    0   0   0   00000000    0   0   0
eth0    0000A8C0    00000000    0001    0   0   1   00FFFFFF    0   0   0
eth1    0028A8C0    00000000    0001    0   0   1   00FFFFFF    0   0   0

destination 和 mask 字段是十六进制的 - 在 little-endian 机器上是字节反转的 - 并为您提供网络范围。解释是:

  • 任何发往 192.168.0.0/24 网络 (0000A8C0 + 00FFFFFF) 的东西都会进入 eth0,不需要网关(换句话说,它与这台机器在同一个子网上)。
  • 任何发往 192.168.40.0/24 (0028A8C0 + 00FFFFFF) 的东西都会进入 eth1,不需要网关。
  • 发往任何其他地址 (00000000 + 00000000) 的数据包将转到默认网关 192.168.0.1。
    (不确定;这行中的额外标志位或“度量”值可能会将其标记为默认网关。但无论如何,如果它没有非零掩码或位于0.0.0.0 地址范围,在现实世界中对路由没有用处。)

由此我可以推断我的系统在 192.168.0.0/24 和 192.168.40.0/24 网络中有 IP 地址。 /proc/net/fib_trie 上的 grep 命令的输出显示在我的系统上:

           |-- 127.0.0.1
              /32 host LOCAL
           |-- 192.168.0.104
              /32 host LOCAL
           |-- 192.168.40.129
              /32 host LOCAL

这样就清楚地表明我的本地 IP 地址是 192.168.0.104 (eth0) 和 192.168.40.129 (eth1)。 (我们可以忽略 127.0.0.1;它始终是环回接口。)

【讨论】:

  • 我做了一些更多的研究,并想出了一些非常接近你提到的东西。首先,我们可以在 fib_trie 中查找同一分支下“/32 链接”和“/32 主机”的地址对。其次,将“/32 link”的地址与/proc/net/route 中的“destination”地址匹配。最后,步骤2中匹配行的/proc/net/route中的接口名称是步骤1中“/32主机”地址的接口名称。是这个过程,特别是匹配“/32链接”到' /proc/net/route 中的目标地址,用于获取正确的网络接口名称?
  • 我真的看不出您从/32 link 行中获得了哪些额外信息。来自/proc/net/route(在我的示例中为00FFFFFF)的网络掩码信息告诉您网络掩码是255.255.255.0(== /24)。并且目标字段为您提供“基本网络地址”(在这种情况下,除了地址的最后一个元组之外的所有地址)。将其与来自/proc/net/fib_trie/32 host 地址相结合,已经为您提供了每个地址所服务的接口及其子网范围的唯一答案。
  • 我发现了什么(我不确定这是否永远成立)但是从/proc/net/fib_trie 例如,我的一个分支有 10.0.2.0 用于 /32 链接和对应的 10.0.2.15 用于 / 32 主机。然后,我在/proc/net/route 中看到 Iface=enp0s3 和 Destination=0002000A (10.0.2.0) 的一行。我看到上面得到的 /32 主机的 10.0.2.15 实际上与我的任何 Ifaces 目的地都不匹配。但是,/32 链接的 10.0.2.0 与 enp0s3 的目标 (10.0.2.0) 匹配。因此,我可以得出结论,来自 fib_trie 的 IP 对属于 enp0s3。 (enp0s3 有来自 ip addr show 的 IP 10.0.2.15/24)
  • 路由表已经告诉你盒子上的子网(目的地+掩码);每个都与一个接口相关联。 fib_trie "/32 Host" 条目告诉您您的 IP 地址。然后,您只需要弄清楚每个 IP 地址属于 哪个 子网即可找到接口。对于路由表中的每个子网条目,测试 IP 是否适合子网:换句话说,IP_Address & Mask == Destination(其中& 是按位与)。如果是这样,您已经找到了匹配的接口。十六进制的 10.0.2.15(字节翻转)是 0F02000A。 (0F02000A & 00FFFFFF) == 0002000A => 匹配 enp0s3
  • 如果不清楚,我并不是说您不能使用 /32 链接条目。我只是没有看到他们添加了您从路由条目中没有的任何信息。
猜你喜欢
  • 2013-06-21
  • 1970-01-01
  • 2012-08-02
  • 2019-08-19
  • 1970-01-01
  • 2012-03-15
  • 2017-10-05
  • 2021-12-19
  • 1970-01-01
相关资源
最近更新 更多