有了getent hosts localhost
,我才得到::1
,虽然我期待127.0.0.1
。我禁用了 IPv6,所以得到::1
更令人惊讶。更令人困惑的是,当 I 时ping localhost
,ping 被发送到127.0.0.1
哪个有效。有人可以解释一下吗?
~: getent hosts localhost
::1 localhost
~: grep 'hosts:' /etc/nsswitch.conf
hosts: files mymachines myhostname resolve [!UNAVAIL=return] dns
~: cat /etc/sysctl.d/disable_ipv6.conf
net.ipv6.conf.all.disable_ipv6=1
~: ping ::1
connect: Network is unreachable
~: ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.022 ms
~: ping localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.015 ms
编辑:localhost
我的/etc/hosts
.
找到这并不容易(但很有趣:))。
简短的回答
使用 __lookup_name() 的 gethostbyname2() 具有一些用于 loopback ('lo') 接口的硬编码值。当您为“getent hosts”命令指定“localhost”时,它最终会在尝试 IPv4 之前使用 IPv6 的默认值,因此您最终会得到 ::1。您可以更改 getent 的代码以获得 127.0.0.1 ,如下所示:
结果:
更多细节
getent 工具使用由musl 库定义和实现的函数。当我们运行命令时
该工具调用 getent.c 下的 hosts_keys() 函数来解析提供的密钥。该函数尝试通过 4 种方法解析:
所有 musl 功能都在 /src/network/ 下实现,请参见此处。gethostbyname2()(在 gethostbyname2.c 中实现)调用 gethostbyname2_r()(在 gethostbyname2_r.c 中实现),后者调用 __lookup_name()(在 lookup_name.c 中)。__lookup_name(),同样,作为如何解析主机名的几个选项,第一个是 name_from_null(在同一个文件中):
最后,我们可以看到,当 family == AF_INET6 时,我们将获得 ::1 的硬编码值。由于 getent 在 IPv4 之前尝试 IPv6,因此这将是返回值。如上所示,在 getent 中强制解析为 IPv4 将导致上述函数的硬编码 127.0.0.1 值。
如果您希望更改功能以返回 localhost 的 IPv4 地址,最好的办法是提交/请求修复,以便 getent 先搜索 IPv4。
希望这可以帮助!