如果没有有效的 resolv.conf,程序如何解析 FQDN?

如果没有有效的 resolv.conf,程序如何解析 FQDN?

我刚刚在嵌入式 Linux 机器中发现了一个由损坏的/etc/resov.conf.具体来说,这是一个损坏的符号链接。我无法解释的是为什么其中一些(许多)曾经起作用。

该代码在 Alpine Linux chroot 内运行。 Debian“主机”有一个当前且正确的 resolv.conf,但 chroot 环境内部的链接已损坏。我还发现默认情况下,Alpine 不附带 nsswitch.conf。所有主机都具有相同的 Alpine linux chroot 环境,它们仅因主机版本 Debian 和网络(物理位置)而有所不同。

主机和 chroot 环境/run /sys /proc /dev仅共享。

尽管如此,某些设备仍可以解析永久 FQDN。我原以为这可能与共享 DNS 缓存有关,但已排除这一点。从 chroot 内部:

$ ping unix.stackexchange.com
PING unix.stackexchange.com (151.101.193.69): 56 data bytes
64 bytes from 151.101.193.69: seq=0 ttl=58 time=3.962 ms

这些嵌入式设备之前不可能被要求解析 unix.stackexchange.com,因此它不应位于其 DNS 缓存中。

我们目前正在调查“工作”和“损坏”设备之间的区别是否在于它们所在的网络或发布版本的细微差别。如果我们能深入了解该细节,我将更新问题。

谁能解释一下为什么一些这些设备中的哪些可能在没有有效 resolv.conf 的情况下解析 FQDN?


有关 chroot 的其他详细信息

  • 所有这些都运行相同的 chroot 映像。
  • chroot环境是一个“库存”Alpine 迷你根文件系统仅通过添加 python3 apk add
  • (前面提到过)chroot 文件系统没有nsswitch.conf且只有一个非常损坏的链接/etc/resolv.conf

有关主机的其他详细信息:

答案1

/etc/resolve.conf不是解析主机的必需组件。权威接口是getaddrinfo(或已弃用的gethostbyname)库函数,应用程序调用该函数来解析主机名。根据系统的配置方式,resolv.conf可能会或可能不会进行咨询。

例如,当 DNS 查询通过systemd-resolved(在 中配置为这样做/etc/nsswitch.conf)路由时,不需要/etc/resolv.conf。根据systemd-resolved依次配置的方式,它使用resolv.conf,或者它可以维持 /run/systemd/resolve/resolv.conf可以从 进行符号链接/etc/resolv.conf。请参阅systemd 解析手册页。

答案2

Alpine Linux 使用 Busybox 和 uClibc,而不是更知名的glibc。 uClibc 的实现有一个怪癖获取地址信息()localhost:53当它在 中找不到其他名称服务器时,它将向其中发送 DNS 请求/etc/resolv.conf

这解释了为什么尽管具有相同的 chroot 环境,某些单元仍以这种方式执行,而其他单元则不然。

它似乎dnsmasq安装在某些主机上,而不是其他主机上。大概是由于 BeagleBone 开发人员不断变化的决定。

belo的跟踪ping -c1 unix.stackexchange.com显示 Alpine / Busybox / ping 尝试打开/etc/resolv.conf,当失败时,它会向 发送请求127.0.0.1:53。然后它会收到该地址的响应。

execve("/bin/ping", ["ping", "-c1", "unix.stackexchange.com"], 0xbec18768 /* 20 vars */) = 0
set_tls(0xb6f215ec)                     = 0
set_tid_address(0xb6f221a0)             = 18047
mprotect(0x536000, 8192, PROT_READ)     = 0
getuid32()                              = 0
getpid()                                = 18047
open("/etc/hosts", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
fcntl64(3, F_SETFD, FD_CLOEXEC)         = 0
read(3, "127.0.0.1\tlocalhost localhost.lo"..., 1024) = 79
read(3, "", 1024)                       = 0
close(3)                                = 0
open("/etc/resolv.conf", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
clock_gettime(CLOCK_REALTIME, {tv_sec=1595644595, tv_nsec=840201586}) = 0
clock_gettime(CLOCK_REALTIME, {tv_sec=1595644595, tv_nsec=840992292}) = 0
socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 3
bind(3, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
clock_gettime(CLOCK_REALTIME, {tv_sec=1595644595, tv_nsec=843970581}) = 0
sendto(3, "\247\206\1\0\0\1\0\0\0\0\0\0\4unix\rstackexchange\3"..., 40, MSG_NOSIGNAL, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, 16) = 40
sendto(3, "\270D\1\0\0\1\0\0\0\0\0\0\4unix\rstackexchange\3"..., 40, MSG_NOSIGNAL, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, 16) = 40
poll([{fd=3, events=POLLIN}], 1, 2500)  = 1 ([{fd=3, revents=POLLIN}])
recvfrom(3, "\247\206\201\200\0\1\0\4\0\0\0\0\4unix\rstackexchange\3"..., 512, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, [16]) = 104
recvfrom(3, "\270D\201\200\0\1\0\0\0\1\0\0\4unix\rstackexchange\3"..., 512, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, [16]) = 124
close(3)                                = 0
ioctl(1, TIOCGWINSZ, {ws_row=38, ws_col=178, ws_xpixel=0, ws_ypixel=0}) = 0
writev(1, [{iov_base="PING unix.stackexchange.com (151"..., iov_len=47}, {iov_base=" data bytes\n", iov_len=12}], 2PING unix.stackexchange.com (151.101.65.69): 56 data bytes
) = 59
socket(AF_INET, SOCK_RAW, IPPROTO_ICMP) = 3
dup2(3, 0)                              = 0
close(3)                                = 0
setsockopt(0, SOL_SOCKET, SO_BROADCAST, [1], 4) = 0
setsockopt(0, SOL_SOCKET, SO_RCVBUF, [7280], 4) = 0
rt_sigprocmask(SIG_UNBLOCK, [RT_1 RT_2], NULL, 8) = 0
rt_sigaction(SIGINT, {sa_handler=0x475b3c, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0xb6ec89fc}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
clock_gettime(CLOCK_MONOTONIC, {tv_sec=4280439, tv_nsec=868933133}) = 0
sendto(0, "\10\0Z\r\177F\0\0\5\16\31\236\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 64, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("151.101.65.69")}, 28) = 64
rt_sigaction(SIGALRM, {sa_handler=0x475b3c, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0xb6ec89fc}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
setitimer(ITIMER_REAL, {it_interval={tv_sec=0, tv_usec=0}, it_value={tv_sec=10, tv_usec=0}}, {it_interval={tv_sec=0, tv_usec=0}, it_value={tv_sec=0, tv_usec=0}}) = 0
recvfrom(0, "E\0\0T8<\0\0:\1\253\215\227eAE\300\250\3\215\0\0b\r\177F\0\0\5\16\31\236"..., 192, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("151.101.65.69")}, [16]) = 84
clock_gettime(CLOCK_MONOTONIC, {tv_sec=4280439, tv_nsec=879592488}) = 0
writev(1, [{iov_base="64 bytes from 151.101.65.69: seq"..., iov_len=56}, {iov_base="\n", iov_len=1}], 264 bytes from 151.101.65.69: seq=0 ttl=58 time=10.659 ms
) = 57
rt_sigaction(SIGINT, {sa_handler=SIG_IGN, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0xb6ec89fc}, {sa_handler=0x475b3c, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0xb6ec89fc}, 8) = 0
writev(1, [{iov_base="", iov_len=0}, {iov_base="\n", iov_len=1}], 2
) = 1
writev(1, [{iov_base="--- unix.stackexchange.com", iov_len=26}, {iov_base=" ping statistics ---\n", iov_len=21}], 2--- unix.stackexchange.com ping statistics ---
) = 47
writev(1, [{iov_base="1 packets transmitted, 1 packets"..., iov_len=45}, {iov_base=" packet loss\n", iov_len=13}], 21 packets transmitted, 1 packets received, 0% packet loss
) = 58
writev(1, [{iov_base="round-trip min/avg/max = 10.659/"..., iov_len=45}, {iov_base=" ms\n", iov_len=4}], 2round-trip min/avg/max = 10.659/10.659/10.659 ms
) = 49
exit_group(0)                           = ?
+++ exited with 0 +++

相关内容