Важно: если имя найдено на одном из шагов, например, в hosts, последующие источники не используются.
В минималистичных системах, таких как Alpine Linux с musl, порядок может отличаться, так как musl не использует NSS и реализует DNS-запросы напрямую, читая /etc/hosts и resolv.conf самостоятельно.
Некоторые приложения и языки (например, Go, Java, Node.js) могут использовать собственные DNS-резолверы, полностью игнорируя системные настройки.
Для примера проанализируем работу утилиты curl.
Команда:
strace -f -e trace=network curl -s download.astralinux.ru > /dev/null
Вывод strace:
socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP) = 3
socketpair(AF_UNIX, SOCK_STREAM, 0, [3, 4]) = 0
socketpair(AF_UNIX, SOCK_STREAM, 0, [5, 6]) = 0
strace: Process 283163 attached
[pid 283163] socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 7
[pid 283163] connect(7, {sa_family=AF_UNIX, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (Нет такого файла или каталога)
[pid 283163] socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 7
[pid 283163] connect(7, {sa_family=AF_UNIX, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (Нет такого файла или каталога)
[pid 283163] socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 7
[pid 283163] connect(7, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.24.31.107")}, 16) = 0
[pid 283163] sendmmsg(7, [{msg_hdr={msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\250\207\1\0\0\1\0\0\0\0\0\0\10download\nastralinux"..., iov_len=40}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, msg_len=40}, {msg_hdr={msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\240\215\1\0\0\1\0\0\0\0\0\0\10download\nastralinux"..., iov_len=40}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, msg_len=40}], 2, MSG_NOSIGNAL) = 2
[pid 283163] recvfrom(7, "\250\207\201\200\0\1\0\1\0\0\0\0\10download\nastralinux"..., 2048, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.24.31.107")}, [28->16]) = 56
[pid 283163] recvfrom(7, "\240\215\201\200\0\1\0\0\0\1\0\0\10download\nastralinux"..., 65536, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.24.31.107")}, [28->16]) = 114
[pid 283163] sendto(6, "\1", 1, MSG_NOSIGNAL, NULL, 0) = 1
[pid 283163] +++ exited with 0 +++
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 5
setsockopt(5, SOL_TCP, TCP_NODELAY, [1], 4) = 0
setsockopt(5, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
setsockopt(5, SOL_TCP, TCP_KEEPIDLE, [60], 4) = 0
setsockopt(5, SOL_TCP, TCP_KEEPINTVL, [60], 4) = 0
connect(5, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("130.193.50.59")}, 16) = -1 EINPROGRESS (Операция выполняется в данный момент)
getsockopt(5, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
getpeername(5, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("130.193.50.59")}, [128->16]) = 0
getsockname(5, {sa_family=AF_INET, sin_port=htons(48488), sin_addr=inet_addr("172.24.31.241")}, [128->16]) = 0
sendto(5, "GET / HTTP/1.1\r\nHost: download.a"..., 86, MSG_NOSIGNAL, NULL, 0) = 86
recvfrom(5, "HTTP/1.1 200 OK\r\nServer: nginx/1"..., 102400, 0, NULL, NULL) = 1617
🔍 Что мы видим в этом strace?
1. Попытка использовать NSCD (Name Service Cache Daemon)
connect(..., "/var/run/nscd/socket", ...) = -1 ENOENT- Это означает, что glibc сначала пытается использовать кеш имён из NSCD, если он запущен. В системе его нет, и запрос идёт дальше.
2. Вызов
socket() и connect() к DNS-серверуsocket(AF_INET, SOCK_DGRAM|..., IPPROTO_IP) = 7
connect(7, ..., sin_addr=inet_addr("172.24.31.107")...)- Здесь создаётся UDP-сокет для обращения к DNS-серверу, указанному в /etc/resolv.conf.
3. Вызов
sendmmsg() — отправка DNS-запросовsendmmsg(7, [ { "download.astralinux.ru" }, { "download.astralinux.ru" } ], ...)
Здесь отправляются запросы на резолв имени. 4. Ответ от DNS
recvfrom(...) = 56
recvfrom(...) = 114Теперь IP-адрес известен.
56 - это размер DNS-ответа в байтах, содержащего А-запись (IPv4-адрес)