仅使用 proc 获取本地网络接口地址?
如何仅使用 proc 获取所有网络接口的 (IPv4) 地址?经过一番广泛的调查后,我发现了以下内容:
ifconfig
使用SIOCGIFADDR
,这需要打开套接字并预先了解所有接口名称。 Linux 上的任何手册页中也没有对此进行记录。proc
包含/proc/net/dev
,但这是一个接口统计信息列表。proc
包含/proc/net/if_inet6
,这正是我所需要的,但对于 IPv6。- 一般来说,接口很容易在 proc 中找到,但实际地址很少使用,除非明确属于某些连接的一部分。
- 有一个名为
getifaddrs
的系统调用,这是一个非常“神奇”的函数您希望在 Windows 中看到。它也在 BSD 上实现。然而它不是非常面向文本,这使得它很难在非 C 语言中使用。
How can I obtain the (IPv4) addresses for all network interfaces using only proc? After some extensive investigation I've discovered the following:
ifconfig
makes use ofSIOCGIFADDR
, which requires open sockets and advance knowledge of all the interface names. It also isn't documented in any manual pages on Linux.proc
contains/proc/net/dev
, but this is a list of interface statistics.proc
contains/proc/net/if_inet6
, which is exactly what I need but for IPv6.- Generally interfaces are easy to find in
proc
, but actual addresses are very rarely used except where explicitly part of some connection. - There's a system call called
getifaddrs
, which is very much a "magical" function you'd expect to see in Windows. It's also implemented on BSD. However it's not very text-oriented, which makes it difficult to use from non-C languages.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
/proc/net/fib_trie
保存网络拓扑为了简单地打印所有适配器的地址:
要确定这些地址的适配器 (a) 从
/proc/net 查询适配器的目标网络/route
,(b) 将这些网络与/proc/net/fib_trie
的网络进行匹配,(c) 打印这些网络下列出的相应 /32 主机地址。不幸的是,再次没有
python
,而是一个相当笨拙的bash
方法:输出:
已知限制:
此方法对于与其他主机地址共享网络的主机地址不能可靠地工作。网络唯一性的丧失使得无法从 fib_trie 确定正确的主机地址,因为这些地址的顺序不一定与路由网络的顺序匹配。
话虽如此,我不确定为什么您首先想要属于同一网络的多个主机地址。因此,在大多数用例中,这种方法应该可以正常工作。
/proc/net/fib_trie
holds the network topographyTo simply print the addresses of all adapters:
To determine the adapter of those addresses (a) consult the adapters' destination networks from
/proc/net/route
, (b) match those networks with the ones of/proc/net/fib_trie
and (c) print the corresponding /32 host addresses listed under those networks.Again no
python
unfortunately, but a quite awkybash
approach:output:
Known limitation:
This approach does not work reliably for host addresses that share the network with other host addresses. This loss of network uniqueness makes it impossible to determine the correct host address from fib_trie as the order of those addresses does not necessarily match the order of networks of route.
Having said that, I'm not sure why you would want multiple host addresses belonging to the same network in first place. So in most use cases this approach should work just fine.
您可能会发现
ip addr show
的输出比其他工具的输出更容易解析:另一个选项是文件
/proc/net/tcp
。它显示了所有当前打开的 TCP 会话,这与您要求的不同,但可能足够好。我的 IP 是
192.168.0.121
;记下有趣的算术以使其结果正确。 :)You may find the output of
ip addr show
easier to parse than output from other tools:Another option is the file
/proc/net/tcp
. It shows all currently-open TCP sessions, which is different than what you asked for, but might be Good Enough.My IP is
192.168.0.121
; note the funny arithmetic to make it come out right. :)我仅使用
/proc
检索 IPv4 网络配置的解决方案:不幸的是,这是 bash (仅 bash 并且没有任何分支),而不是python。但我希望这将是可读的:
有一个输出示例:
说明:
我使用 IPV4 的整数值来检查 IP 和 IP。掩码==网络。
我首先阅读
/proc/net/route
来查找路由配置,搜索无需任何网关即可到达的路由 (gw==000000
)。对于这样的路由,我在所有连接(TCP,如果在 TCP 中未找到则为 UDP)中搜索使用 this 路由的连接,第一个端点是我的主机地址。
注:这不适用于 PPP 连接。
注 2:这不适用于没有任何打开的网络连接的完全安静的主机。
你可以做类似的事情
echo -ne '' | nc -q 0 -w 1 8.8.8.8 80 &睡眠.2 && ./retrieveIp.sh
用于确保在/proc/net/tcp
中找到某些内容。Nota3,2016-09.23:新 bash 版本使用
>(command)
语法进行多个内联管道
功能。这意味着第 18 行存在错误:>
和(
之间必须存在空格!!带有网关的新版本 em>
有一个小补丁:通过复制之前的脚本创建名为
getIPv4.sh
的文件后,您可以将以下内容粘贴到命令中:patch -p0
以Ctrld,这可能会输出:
然后
重新运行您的脚本:
My solution to retrieve IPv4 network config, using
/proc
only:Unfortunately, this is bash (bash only and without any fork), not python. But I hope this will be readable:
There is a sample of output:
Explanation:
I use integer value of IPV4 in order to check
IP & MASK == NETWORK
.I read first
/proc/net/route
to find routing configurations, searching for routes reachable without any gateway (gw==000000
).For such a route, I search in all connections (TCP, than UDP if not found in TCP) for connection using this route, the first end point is my host address.
Nota: This won't work with PPP connections
Nota2: This won't work on a totally quiet host without any opened network connection.
You could do something like
echo -ne '' | nc -q 0 -w 1 8.8.8.8 80 & sleep .2 && ./retrieveIp.sh
for ensuring that something where found in/proc/net/tcp
.Nota3, 2016-09.23: New bash version use
>(command)
syntax formultiple inline pipe
feature. This implie a bug at line 18: a space must be present between>
and(
!!New version with gateway
There is a little patch: Once you create a file called
getIPv4.sh
by copying previous script, you could paste the following to the command:patch -p0
End with Ctrld, this may output:
And maybe
Then re-run your script:
ifconfig没有 /proc/net/if_inet6 的 IPv4 类似功能
:
您将得到如下内容:
There is no IPv4 analog of /proc/net/if_inet6
ifconfig does:
You'll get something like this:
这是我在互联网上找到的一件漂亮的东西。对其进行了小幅修复,以适应并正确输出 tun (vpn) 设备。
hers a fancy one i found somewhere in the internet. minorly fixed it up to fit and correctly output tun (vpn) devices.
cat /proc/net/tcp
获取第二列,标题为“local_address”,例如“CF00A8C0:0203”
“:”后面的部分是端口号。
其余的使用最后两个(C0)作为十六进制数,例如C0 是192,这是本例中地址的开始。
不久前,我从网络上的一些聪明点将以下内容记入我的笔记中:
IP地址显示为小端四字节十六进制数;
也就是说,首先列出最低有效字节,
因此您需要颠倒字节顺序才能将其转换为 IP 地址。
端口号是一个简单的两字节十六进制数。
cat /proc/net/tcp
Get the second column, with the heading "local_address", e.g. "CF00A8C0:0203"
The part after ":" is a port number.
From the rest use the last two (C0) as a hex number, e.g. C0 is 192, which is the start of the address in this example.
Took the following into my notes a while ago, from some smart point in the net:
The IP address is displayed as a little-endian four-byte hexadecimal number;
that is, the least significant byte is listed first,
so you'll need to reverse the order of the bytes to convert it to an IP address.
The port number is a simple two-byte hexadecimal number.
请注意 /proc/net/tcp,因为在我这里的系统上,我使用 keepalived 在首选主机上调出一个额外的 IP 地址,但当我检查时,该地址并未在 /proc/net/tcp 中表示,但它存在于 /proc/net/fib_trie 中
Beware of /proc/net/tcp as on a system I have here, I use keepalived to bring up an additional IP address on the preferred host, but when I checked, that address wasn't represented in /proc/net/tcp, but it is present in /proc/net/fib_trie
在 miniss 中,我通过读取
/proc/net/tcp< 显示打开的侦听套接字列表/code>、
/proc/net/tcp6
、/proc/net/udp
、/proc/net/udp6
而不是使用ss
或netstat
。您的问题类似,您想读取
/proc/net/
中的一些文件,而不是使用ip
或ifconfig
。在大多数
/proc/net/
中,IP 地址以特定方式进行十六进制编码(请参阅 水晶源代码在这里查看如何解码它们,可以在 python 中重现)。正如其他人所说,对于 IPv6 有方便的
/proc/self/net/if_inet6
但对于 IPv4 没有等效的。因此,对于 IPv4,您可以在网络上的/proc/net/fib_trie
和/proc/net/route
之间创建映射。最难的是解析 IP 地址,但我只是给了你这样做的源代码。In miniss I display the list of open listening sockets by reading
/proc/net/tcp
,/proc/net/tcp6
,/proc/net/udp
,/proc/net/udp6
instead of usingss
ornetstat
.Your issue is similar, where you want to read some files in
/proc/net/
instead of usingip
orifconfig
.In most
/proc/net/
, IP addresses are hex encoded in a specific way (see the crystal source code here to see how to decode them, that could be reproduced in python).As said by others, there is the convenient
/proc/self/net/if_inet6
for IPv6 but no equivalent for IPv4. So for IPv4 you could make a map between/proc/net/fib_trie
and/proc/net/route
on the network. The hardest is parsing IP addresses but I just gave you the source code to do so.这是低音-落后,我可能忘记了一个极端情况,但如果你看一下 /proc/1/net/route,那有你的路由表。如果您选择网关为 0.0.0.0 的行,则第一列是接口,第二列是以网络字节顺序表示的 IP 地址的十六进制表示形式(第三列是要过滤的网关 IP) )。
It's bass-ackwards and I probably am forgetting a corner case, but if you look at /proc/1/net/route, that has your routing table. If you select lines for which the gateway is 0.0.0.0, the first column is the interface and the second column is the hex representation of your IP address, in network byte order (and the third column is the gateway ip you want to filter on).