Повільний DNS не здається «проблемою DNS». Це більше схоже на затримки в SSH, зависання інсталяцій пакетів, тайм‑аути CI, флапінг перевірок Kubernetes і намагання розробників стверджувати «мережа в порядку», бо ping працює.
У сучасному Linux ця мука часто проходить через systemd-resolved. Не тому, що це погане програмне забезпечення, а тому, що воно знаходиться на перетині хибних припущень: зламані search‑домени, VPN зі split DNS, NAT64, очікування DNSSEC, captive‑портали і древня поведінка резольвера вбудована в libc. Виправлення рідко буває «вимкнути його». Треба спостерігати весь ланцюжок резольвера й змінити ту одну річ, яка реально додає секунди.
Швидкий план діагностики
Якщо DNS‑запити відчуваються повільними, не починайте з редагування конфігів. Спочатку доведіть, де саме витрачається час. Ви шукаєте: повтори, розгортання search‑доменів, затримки через fallback IPv6/IPv4, зависання валідації DNSSEC або локальний stub, який зовсім не локальний.
1) Підтвердіть, що це DNS, а не TCP
Виберіть hostname, який у вашому додатку поводиться повільно (не тестовий домен). Виміряйте розв’язання імен окремо від встановлення з’єднання.
cr0x@server:~$ time getent ahosts api.internal.example
192.0.2.41 STREAM api.internal.example
192.0.2.41 DGRAM
192.0.2.41 RAW
real 0m2.183s
user 0m0.010s
sys 0m0.006s
Що це означає: getent використовує той самий NSS‑шлях, що й ваші програми. Якщо це займає секунди — ви знайшли потрібну підсистему.
Рішення: Якщо getent повільний, але прямий dig @server швидкий, горло пляшки — локальна логіка резольвера (search‑домени, порядок NSS, поведінка stub), а не upstream DNS.
2) Визначте активний шлях резольвера
cr0x@server:~$ resolvectl status
Global
Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Current DNS Server: 10.0.0.53
DNS Servers: 10.0.0.53 10.0.0.54
DNS Domain: corp.example
Link 2 (ens192)
Current Scopes: DNS
Protocols: +DefaultRoute -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 10.0.0.53
DNS Servers: 10.0.0.53 10.0.0.54
DNS Domain: corp.example
Що це означає: Це показує, чи задіяний systemd-resolved і які DNS‑сервери й домени він бачить.
Рішення: Якщо resolv.conf mode — stub, додатки, ймовірно, питатимуть 127.0.0.53. Якщо це foreign або static, хтось інший керує /etc/resolv.conf — налагоджуйте цього власника.
3) Шукайте повтори й таймаути
cr0x@server:~$ resolvectl query api.internal.example
api.internal.example: 192.0.2.41 -- link: ens192
-- Information acquired via protocol DNS in 2.127s.
-- Data is authenticated: no
Що це означає: Час «acquired in» — це видимий для користувача біль.
Рішення: Якщо це >200ms послідовно в LAN — ймовірно ви бачите таймаути/повтори або зламаний search‑домен. Перейдіть до перехоплення пакетів або логів resolved.
4) Відрізніть «повільний upstream DNS» від «повільної поведінки резольвера»
cr0x@server:~$ dig +tries=1 +time=1 @10.0.0.53 api.internal.example A
; <<>> DiG 9.18.24-1ubuntu1.2-Ubuntu <<>> +tries=1 +time=1 @10.0.0.53 api.internal.example A
;; global options: +cmd
;; ANSWER SECTION:
api.internal.example. 60 IN A 192.0.2.41
;; Query time: 7 msec
;; SERVER: 10.0.0.53#53(10.0.0.53) (UDP)
;; WHEN: Wed Dec 31 12:12:12 UTC 2025
;; MSG SIZE rcvd: 68
Що це означає: Upstream DNS швидкий. Проблема в локальному шляху резольвера.
Рішення: Сконцентруйтесь на конфігурації systemd-resolved, NSS і stub. Не витрачайте тиждень на крики до DNS‑команди.
Ланцюжок резольвера: де ховаються секунди
Розв’язання імен у Linux — це не «один DNS‑запит». Це ланцюжок рішень, і кожне рішення може додати затримку.
Шлях, яким насправді працюють більшість
- Додаток викликає
getaddrinfo()(часто і для A, і для AAAA). Деякі додатки роблять це в гарячому шляху. Деякі роблять це при кожному запиті, бо кешування «складне». - glibc консультується з NSS через
/etc/nsswitch.confі проходить по джерелах (files, resolve, dns, mdns, wins…). Порядок має значення. Обробка помилок — ще важливіша. - Якщо
systemd-resolvedувімкнений і NSS налаштований наresolve, glibc говорить з resolved через D‑Bus або модуль nss‑resolve. Інакше glibc використовує/etc/resolv.confі відправляє DNS‑пакети напряму. - Якщо
/etc/resolv.confвказує на127.0.0.53, ваш «nameserver» — локальний stub на localhost. Цей stub пересилає запити вгору, застосовує split DNS маршрутизацію, кешує, може валідовувати DNSSEC і намагається бути корисним. - Upstream‑сервери можуть бути локальними кешуючими резольверами, корпоративним DNS, резольвером, наданим VPN, або тим, що ваш ноут отримав від DHCP у готелі і що мало б бути забороненим.
Симптом «DNS повільний» може походити з будь‑якого шару. І так, dig може бути швидким тоді як ваш додаток — повільним, бо dig обходить частину цього ланцюжка. Якщо ви діагностуєте лише за допомогою dig, ви налагоджуєте не ту систему.
Одна цитата, яку варто пам’ятати під час цієї гонитви: «Сподівання — це не стратегія.»
— General Gordon R. Sullivan. Це не тільки про DNS, але дуже застосовно.
Жарт №1: DNS — єдине місце, де «це завжди мережа» і «це ніколи не мережа» одночасно якимось чином правдиві.
Факти і історія, що пояснюють сьогоднішні дивності
- Поведінка оригінального резольвера передує вашій хмарі. Логіка за замовчуванням щодо «search domain» походить з епохи, коли
printerрезолвився якprinter.office, і витрати додаткових запитів ігнорувалися. - NSS — це система плагінів, не лише DNS. Пошук імен може залучати локальні файли, LDAP, mDNS, WINS і резольвер systemd. Неправильний порядок додає секунди на кожен виклик.
- systemd-resolved популяризував локальний stub. Та адреса
127.0.0.53— не «справжній DNS‑сервер», це зручний шар для підтримки split DNS, кешування і політики. - Негативне кешування — це функція продуктивності. Без нього опечатки й мертві домени перетворювалися б на повторні таймаути. Але з ним неправильні налаштування можуть «прилипати» до кешу, поки не мине TTL.
- AAAA‑запити стали стандартом, і це змінило затримки. Клієнти з подвійним стеком часто питають AAAA і A; зламані IPv6‑шляхи можуть додавати затримки навіть коли IPv4 працює.
- EDNS(0) покращив DNS, але MTU зіпсував усе. Великі UDP‑відповіді корисні для сучасних записів, але коли path MTU discovery ламається, ви отримуєте повтори й відкат на TCP, що виглядає як «випадкова повільність».
- DNSSEC — дешево, поки не стає дорого. Валідація зазвичай мало затратна, але проблеми з часом або зламані upstream‑ланцюги можуть спричинити додаткові запити і затримки.
- VPN зробив split DNS нормою. Корпоративні середовища часто направляють певні суфікси до внутрішніх резольверів, а все інше — до публічних. Це двигун політики, а не «просто DNS».
Як виглядає «повільний DNS» (і чому dig може брехати)
Ось класичні патерни:
- Перший запит повільний, далі швидко. Якийсь шар кешує, але перший промах дорогий (таймаути або розширення списку search).
- Лише деякі імена повільні. Зазвичай це split DNS маршрутизація (неправильний інтерфейс), витік внутрішньої зони або DNS‑сервер, який може вирішувати публічні імена, але не приватні (або навпаки).
- Лише деякі програми повільні. Додатки, що використовують libc/NSS, повільні; інструменти на зразок
dig— швидкі. Це вказує на порядок NSS, поведінку stub resolved або відкат IPv6/IPv4. - Все повільно після підключення VPN. VPN підсунув search‑домени й/або DNS, і тепер кожне одно‑міткове ім’я генерує невелику бурю запитів.
- Перервні багатосекундні сплески. Повторні відправлення через втрату UDP, проблеми з MTU або DNS‑сервер, який інколи недоступний.
- NXDOMAIN повільний. Негативні відповіді йдуть довгим шляхом (search‑домени) або таймаутяться через невідповідність DNS‑серверів.
Жарт №2: Якщо хочете відчути подорож у часі, запустіть apt update на ноуті з поганим списком search‑доменів.
Практичні завдання: команди, виводи, рішення
Це не «випадкові команди». Кожна відповідає на конкретне питання й має вплинути на ваші подальші дії.
Завдання 1: Доведіть, що повільний шлях використовує libc/NSS
cr0x@server:~$ time getent hosts github.com
140.82.121.3 github.com
real 0m1.612s
user 0m0.003s
sys 0m0.004s
Значення: getent hosts використовує NSS. Якщо це повільно — ваші додатки будуть повільні.
Рішення: Продовжуйте перевірки NSS і resolved. Якщо getent швидкий, але ваш додаток повільний, то проблема в самому додатку (proxy, TLS, OCSP або цикли повторів).
Завдання 2: Порівняйте швидкість прямого DNS‑запиту
cr0x@server:~$ time dig +tries=1 +time=1 github.com A | sed -n '1,20p'
; <<>> DiG 9.18.24-1ubuntu1.2-Ubuntu <<>> +tries=1 +time=1 github.com A
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48219
;; ANSWER SECTION:
github.com. 60 IN A 140.82.121.3
Значення: Якщо dig швидкий, а getent повільний — upstream DNS в порядку.
Рішення: Фокус на ланцюжку резольвера (search‑домени, stub, DNSSEC, IPv6).
Завдання 3: Визначте, хто володіє /etc/resolv.conf
cr0x@server:~$ ls -l /etc/resolv.conf
lrwxrwxrwx 1 root root 39 Dec 31 10:02 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf
Значення: Якщо це симлінк на systemd‑овий stub, то використовується локальний stub.
Рішення: Не редагуйте вручну /etc/resolv.conf. Ви програєте. Налаштуйте менеджер (resolved, NetworkManager, netplan або ваш DHCP‑клієнт).
Завдання 4: Перегляньте вміст stub і search‑домени
cr0x@server:~$ cat /etc/resolv.conf
# This file is managed by man:systemd-resolved(8). Do not edit.
nameserver 127.0.0.53
options edns0 trust-ad
search corp.example dev.corp.example
Значення: Великі або неправильні списки search спричиняють додаткові запити. Деякі резольвери також застосовують поведінку типу ndots; libc також використовує options.
Рішення: Якщо список search довгий — скоротіть його на джерелі (DHCP/VPN) або встановіть per‑link домени у resolved через ваш мережевий менеджер.
Завдання 5: Перевірте порядок NSS (тиха проблема продуктивності)
cr0x@server:~$ grep -E '^\s*hosts:' /etc/nsswitch.conf
hosts: files mdns4_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] dns
Значення: Такий порядок спочатку пробує локальні файли, потім mDNS, потім systemd‑resolved, потім DNS. mDNS може додавати затримки для не‑.local імен, якщо неправильно налаштований. Квадратні правила важливі.
Рішення: На серверах віддавайте перевагу детермінованій поведінці. Якщо не використовуєте mDNS — приберіть його. Якщо використовуєте resolved — тримайте resolve перед dns, щоб не обходити split‑DNS.
Завдання 6: Подивіться, що бачить resolved
cr0x@server:~$ resolvectl dns
Global: 10.0.0.53 10.0.0.54
Link 2 (ens192): 10.0.0.53 10.0.0.54
Значення: Підтверджує, які DNS‑сервери використовуватиме resolved. Per‑link DNS важливий при VPN та декількох інтерфейсах.
Рішення: Якщо на неправильному інтерфейсі DNS має «DefaultRoute», виправте per‑link налаштування (NetworkManager, netplan або конфіг resolved).
Завдання 7: Виміряйте через resolvectl (обходить NSS, але звертається до resolved)
cr0x@server:~$ resolvectl query -t A -c 1 api.internal.example
api.internal.example: 192.0.2.41 -- link: ens192
-- Information acquired via protocol DNS in 2.044s.
Значення: Повільно тут означає, що шлях пересилання resolved повільний (вибір сервера, повтори, DNSSEC, проблеми з пакетами), а не лише розгортання search.
Рішення: Перевірте логи і зробіть пакетний захват далі.
Завдання 8: Увімкніть дебаг‑логи resolved (тимчасово)
cr0x@server:~$ sudo resolvectl log-level debug
cr0x@server:~$ sudo journalctl -u systemd-resolved -n 50 --no-pager
Dec 31 12:20:11 server systemd-resolved[612]: Sending query for api.internal.example IN A on interface 2/ens192.
Dec 31 12:20:12 server systemd-resolved[612]: Timeout reached on transaction 45123.
Dec 31 12:20:13 server systemd-resolved[612]: Retrying transaction 45123.
Значення: Ви буквально побачите таймаути й повтори.
Рішення: Якщо бачите таймаути — підозрюйте втрату UDP, фаєрвол, неправильний сервер або проблеми з MTU/EDNS. Якщо бачите повторні спроби search‑доменів — підозрюйте список search і одно‑міткові імена.
Завдання 9: Пакетний захват: доведіть повтори або проблеми з фрагментацією
cr0x@server:~$ sudo tcpdump -ni any '(udp port 53 or tcp port 53)' -vv -c 20
tcpdump: listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
12:22:01.123456 ens192 Out IP 10.0.0.10.51234 > 10.0.0.53.53: 45123+ A? api.internal.example. (40)
12:22:02.124987 ens192 Out IP 10.0.0.10.51234 > 10.0.0.53.53: 45123+ A? api.internal.example. (40)
12:22:03.127001 ens192 In IP 10.0.0.53.53 > 10.0.0.10.51234: 45123* 1/0/0 A 192.0.2.41 (56)
Значення: Той самий запит відправлено двічі перед тим, як прийде відповідь — це поведінка повтору, а не «процесор повільний».
Рішення: Якщо повтори часті — шукати втрату пакетів, перевантаження DNS, ліміти фаєрволу або проблеми з MTU. Якщо відповіді приходять лише по TCP — досліджуйте EDNS і фрагментацію.
Завдання 10: Перевірте, чи resolved відкочується на TCP
cr0x@server:~$ resolvectl statistics
Transactions: 2145
Cache: size 1024, hits 1432, misses 713
DNSSEC Verdicts: secure 0, insecure 0, bogus 0, indeterminate 0
Значення: Статистика може натякнути, чи допомагає кеш. Прямо вона не скаже про відкат на TCP, але в поєднанні з tcpdump все стане зрозуміло.
Рішення: Якщо кеш‑місів багато для повторюваних імен — у вас можуть бути крихітні TTL або додатки генерують унікальні імена (божевільна служба discovery).
Завдання 11: Визначте затримки через IPv6 (проблеми AAAA)
cr0x@server:~$ getent ahosts example.com | head
2606:2800:220:1:248:1893:25c8:1946 STREAM example.com
2606:2800:220:1:248:1893:25c8:1946 DGRAM
2606:2800:220:1:248:1893:25c8:1946 RAW
Значення: Якщо AAAA існує, ваш додаток може спробувати IPv6 першим. Якщо маршрутизація IPv6 зламана — побачите затримки з’єднання, які помилково виглядають як затримки DNS.
Рішення: Якщо розв’язання імен швидке, але з’єднання гальмує — виправляйте маршрутизацію/RA/фаєрвол IPv6. Якщо саме розв’язання повільне — продовжуйте налагодження resolved.
Завдання 12: Прослідкуйте один повільний виклик через strace
cr0x@server:~$ strace -f -tt -o /tmp/ga.trace getent hosts api.internal.example
192.0.2.41 api.internal.example
cr0x@server:~$ tail -n 12 /tmp/ga.trace
12:24:41.100112 connect(3, {sa_family=AF_UNIX, sun_path="/run/systemd/resolve/io.systemd.Resolve"}, 110) = 0
12:24:41.100321 sendto(3, "{...}", 224, 0, NULL, 0) = 224
12:24:43.142901 recvfrom(3, "{...}", 4096, 0, NULL, NULL) = 312
12:24:43.143210 close(3) = 0
Значення: Ви бачите 2‑секундну паузу між send і receive. Це затримка резольвера, а не процесора додатку.
Рішення: Якщо затримки відбуваються до звернення до resolved (наприклад, ітерація файлів, mdns), виправляйте порядок NSS. Якщо затримки — у очікуванні resolved, виправляйте resolved/upstream.
Завдання 13: Перевірте конфігурацію systemd-resolved (що ви фактично встановили)
cr0x@server:~$ systemd-analyze cat-config systemd/resolved.conf
# /etc/systemd/resolved.conf
[Resolve]
DNS=10.0.0.53 10.0.0.54
Domains=corp.example
DNSSEC=no
DNSOverTLS=no
Cache=yes
Значення: Це ефективний конфіг, включно з drop‑in. Краще знати, який файл використовується, ніж гадати.
Рішення: Якщо DNSSEC встановлено як «allow-downgrade» або «yes» і ви в заплутаному корпоративному середовищі — встановлюйте політику явно (але робіть це свідомо, а не в паніці).
Завдання 14: Переконайтеся, що /etc/resolv.conf не воює з вашим мережевим менеджером
cr0x@server:~$ resolvectl status | grep -E 'resolv\.conf mode'
resolv.conf mode: stub
Значення: «stub» означає, що інтеграційний шлях працює як задумано.
Рішення: Якщо бачите resolv.conf mode: foreign, знайдіть, хто його перезаписує (часто VPN‑клієнт або старий пакет resolvconf) і припиніть цю тяганину.
Виправте systemd-resolved правильно (патерни налаштування)
«Вимкнути systemd-resolved» — це DNS‑еквівалент вимкнення сигналізації диму, бо вона голосна. Інколи його потрібно замінити, але частіше треба налаштувати так, щоб воно перестало виконувати дорогу роботу за вас.
Патерн A: Виправте search‑домени (тихий множник запитів)
Якщо у вашому /etc/resolv.conf кілька search‑доменів, lookup для db стає:
db.corp.exampledb.dev.corp.exampledb(залежно від опцій)
Примножте це на A і AAAA, на повтори, на кожний мікросервіс — можна уявити результат.
Що робити: На серверах віддавайте перевагу FQDN у конфігах і тримайте список search коротким. Якщо DHCP шле сміття — виправте DHCP. Якщо VPN шле сміття — виправте профіль VPN. Якщо ніщо не допомагає — примусово встановіть адекватні домени в per‑link конфігурації resolved через ваш мережевий менеджер.
Патерн B: Використовуйте per‑link DNS і routing domains для split DNS
Правильний підхід для корпоративного + інтернету зазвичай — split DNS: внутрішні суфікси на внутрішні резольвери, усе інше — на загальний резольвер. systemd-resolved для цього підходить. Загальна помилка — DNS з «DefaultRoute» опиняється на неправильному інтерфейсі (VPN проти Wi‑Fi), або VPN хоче тільки corp.example, але випадково стає резольвером для всього.
Що робити: Робіть внутрішні домени маршрутизаційними, де це доречно. У семантиці systemd‑resolved префікс ~ перед доменом робить його routing domain. Це означає «надсилай запити для цього суфікса цим DNS‑серверам», а не «додавай цей суфікс до невизначених імен». Ви зменшите марні розширення search і при цьому збережете коректну маршрутизацію.
Патерн C: Визначте політику щодо DNSSEC явно (не дозволяйте дефолтам вас здивувати)
DNSSEC — чудовий, коли ланцюг цілий і час синхронізований. В підприємствах ви зустрінете middlebox‑и, що перезаписують DNS, captive‑портали, які гіжають, і внутрішні зони, що ніколи не були підписані. Це не означає «відключити DNSSEC повсюди». Потрібно вирішити, де ви хочете валідацію, а де ні.
Що робити: На серверах у контрольованій мережі явно задайте політику DNSSEC у /etc/systemd/resolved.conf і перевірте, що upstream її підтримує. На ноутбуках «allow-downgrade» може зменшити кількість звернень у службу підтримки, але це компроміс у безпеці. Приймайте рішення свідомо.
Патерн D: Не воюйте за власність /etc/resolv.conf
Сучасні дистрибутиви очікують, що хтось управляє /etc/resolv.conf. Якщо редагувати його вручну — його перезапишуть. Якщо встановити другий менеджер — з’являться хейзенбаґи.
Що робити: Оберіть один авторитет: NetworkManager, systemd‑networkd/netplan або статичну конфігурацію. Переконайтесь, що ваш VPN‑клієнт інтегрується з цим авторитетом, а не малює поверх /etc/resolv.conf прямо.
Патерн E: Виправляйте таймаути через мережу, а не ховайте їх
Є налаштування для повторів і таймаутів, але якщо вам треба їх змінювати в LAN — щось інше не в порядку: втрата пакетів, правила фаєрволу, перевантажений резольвер, MTU‑blackhole. Ви можете «оптимізувати» навколо цього і все одно програти посеред ночі.
Якщо логи показують таймаути — робіть пакетний захват, ідентифікуйте який сервер повільний і видаліть його з ротації або виправте його. Якщо один із налаштованих DNS‑серверів мертвий — ваш «швидкий DNS» насправді швидкий тільки половину часу.
Три корпоративні історії з практики
Інцидент 1: Неправильне припущення (dig швидкий, отже DNS в порядку)
Середня компанія мала хвилю «перерв у роботі» внутрішніх API. З боку додатків це виглядало як затримки TCP‑connect. Інженери виконували dig по внутрішньому імені і отримували відповіді за кілька мілісекунд. Закрито, думали вони. Команда API почала шукати проблеми в thread pool і балансувальниках навантаження.
Потім хтось запустив getent ahosts і побачив затримки 1–3 секунди, переважно для імен, яких не існувало. Це був перший натяк: сама служба не була повільною, а резольвер гальмував при опитуванні опечаток, застарілих імен сервісів або вимкнутих ендпойнтів.
Коренева причина — довгий список search‑доменів, що штовхав VPN‑профіль. Кожне одно‑міткове ім’я породжувало кілька запитів через split DNS. Деякі суфікси надсилались до резольверів, які не могли на них відповісти і просто таймаутувалися замість відправки NXDOMAIN. Кожен таймаут давав повну секунду або дві. Помножте на повтори і на A+AAAA — отримаєте «перерви».
Виправлення не полягало у вимкненні systemd-resolved. Потрібно було перетворити «Domains» VPN на routing domains для внутрішніх суфіксів, скоротити список search і перестати використовувати одно‑міткові імена в продакшн‑конфігах. Інцидент розвіявся. Постмортем додав правило: для Linux‑сервісів вимірюйте через getent, а не тільки dig.
Інцидент 2: Оптимізація, що відкотилася (змусити «швидший» DNS)
В іншій компанії хтось вирішив, що корпоративні резольвери «повільні», виходячи із кількох тестів на ноутбуках у кав’ярнях. Пропозиція: хардкодити публічні резольвери в /etc/systemd/resolved.conf на всіх робочих станціях розробників. Це запакували в образ як стандартне налаштування.
Продуктивність покращилася для публічних доменів. Потім почали ламатися внутрішні інструменти. Деякі внутрішні зони були розв’язувані лише через корпоративний DNS. Розробники почали додавати хакі: записи в hosts, ad‑hoc скрипти для VPN DNS, і звичку копіпастити IP у конфіги «щоб працювати». Природно, ті IP змінювалися, і хаки перетворювалися на відмови.
Найцікавіше: публічні резольвери були заблоковані в частині корпоративних мереж, тож «оптимізація» викликала таймаути й довгі відступи саме там, де цього найменше хотіли — під час реагування на інциденти в обмежених сегментах.
Виправленням стала відкатна дія і кращий дизайн split DNS: корпоративні суфікси — до корпоративних резольверів, все інше — через локальні мережеві резольвери з кешуванням. Розробники отримали швидкість без ламання внутрішніх імен. Безпека отримала політику. Ops отримали менше тикетів. Всі перестали вдавати, що «один DNS‑сервер підходить для всього» — це стратегія.
Інцидент 3: Нудна правильна практика, що врятувала день (зробити поведінку резольвера видимою)
Велике підприємство не мало ідеального DNS. У них були множинні резольвери, VPN і мікс дистрибутивів. Але у них була нудна дисципліна: кожен імідж фліту мав легкий «скрипт перевірки резольвера» і стандартний набір дебагу, що захоплював resolvectl status, /etc/nsswitch.conf, /etc/resolv.conf і короткий packet trace при тригері.
Одного дня нова політика фаєрволу почала обмежувати UDP‑фрагменти. Ніхто не оголосив це як «DNS‑пов’язане». Першими симптомами були випадкові уповільнення логінів, потім проблеми під час встановлення пакетів, потім таймаути мікросервісів.
Оскільки існував пакет резольвера, на чергового не покладалися здогадки. Він порівняв traces зі здорових і хворих хостів. У хворих хостів були усічені відповіді, відкат на TCP і повторні спроби. Кореляція з певним мережевим сегментом була миттєвою. Вони передали фаєрвол‑команді докази, а не припущення.
Виправлення було точковим: дозволити фрагментовані DNS‑відповіді або виставити менші EDNS‑payload розміри на потрібному шарі. Інцидент закінчився без звичного тижневого каруселю звинувачень. Нудна практика перемогла. Знову.
Типові помилки: симптом → коренева причина → виправлення
1) «dig швидкий, але curl повільний»
Симптом: dig повертає результат швидко; додатки зависають перед підключенням.
Коренева причина: Додатки використовують libc/NSS; dig обходить порядок NSS і може питати інший сервер. Також додатки часто роблять A+AAAA плюс розширення search; ваш тест dig ймовірно робив одиничний запит.
Виправлення: Тестуйте getent ahosts і resolvectl query. Аудитуйте /etc/nsswitch.conf і search‑домени; переконайтесь, що routing у resolved правильний.
2) «Все повільніло після VPN»
Симптом: Розв’язання імен швидке до VPN, повільне після.
Коренева причина: VPN підсовує довгі search‑домени і/або перехоплює дефолтний DNS‑маршрут, відправляючи всі запити до резольвера, доступного лише через перевантажений тунель.
Виправлення: Налаштуйте split DNS з routing domains для внутрішніх суфіксів; тримайте дефолтний DNS на локальному інтерфейсі, якщо політика не вимагає інакше.
3) «NXDOMAIN займає 5 секунд»
Симптом: Опечатки або відсутні записи надто повільні.
Коренева причина: Розширення search‑списку + upstream‑сервери, що таймаутять замість швидкого відповідання; інколи мертвий вторинний DNS‑сервер спричиняє повтори.
Виправлення: Зменшіть search‑домени, видаліть мертвих DNS‑серверів і переконайтесь, що upstream відповідає коректно для неіснуючих імен.
4) «Лише внутрішні домени повільні»
Симптом: Публічні домени резолвяться швидко; внутрішні зони — з затримкою.
Коренева причина: Split DNS маршрутизація неправильно налаштована: внутрішній суфікс надсилається на неправильний резольвер, або декілька інтерфейсів конкурують (Wi‑Fi + VPN + Docker bridge).
Виправлення: Використовуйте per‑link DNS і routing domains; перевірте через resolvectl status, який лінк володіє доменом.
5) «Випадкові сплески: інколи 20ms, інколи 2s»
Симптом: Зазвичай все нормально, інколи затримки.
Коренева причина: Втрата UDP, ліміти фаєрволу, проблеми MTU/EDNS або один із налаштованих DNS‑серверів періодично падає.
Виправлення: Захопіть пакети, дивіться на повтори; видаліть або виправте ненадійні резольвери; виправте MTU або обробку фрагментованих UDP.
6) «systemd-resolved постійно змінює мій resolv.conf»
Симптом: Ручні правки зникають.
Коренева причина: Цей файл не ваш. Його керує resolved або інший мережевий компонент.
Виправлення: Налаштуйте власника (resolved conf, налаштування NetworkManager, netplan/systemd‑networkd). Припиніть редагувати /etc/resolv.conf вручну.
Чек‑лісти / покроковий план
Покроково: від «повільно» до «виправлено» без здогадок
- Виміряйте з правильним інструментом: запустіть
time getent ahosts name. Зафіксуйте реальну затримку. - Перевірте власність:
ls -l /etc/resolv.conf. Якщо це симлінк на stub — resolved у ланцюжку. - Перегляньте search‑домени:
cat /etc/resolv.confіresolvectl status. Якщо search довгий — підозрілий. - Перегляньте порядок NSS: перевірте рядок
hosts:. Видаліть джерела, які не використовуєте (особливо на серверах). - Порівняйте шари:
dig @upstreamvsresolvectl queryvsgetent. Знайдіть, де з’являється затримка. - Коротко увімкніть дебаг: підвищте рівень логів resolved і прочитайте таймаути/повтори.
- Захопіть пакети: підтвердіть повтори, усічення, відкат на TCP або «відсутність відповіді».
- Виправте причину: неправильний DNS‑сервер, мертвий вторинний, зламаний MTU, неправильна split DNS маршрутизація, несумісність DNSSEC або надутий список search.
- Відкотіть debug‑налаштування: поверніть рівень логів до нормального і тримайте журнал чистим.
- Повторно протестуйте й задокументуйте: повторіть ті ж вимірювання і захопіть timing до/після змін.
Операційний чек‑ліст: щоб це не повернулося
- Уніфікуйте, як DNS керується на кожному дистрибутиві (NetworkManager vs networkd) і не змішуйте менеджери на одному хості.
- Визначте дозволені search‑домени для кожного середовища; тримайте production‑сервери консервативними.
- Моніторьте латентність і помилки резольвера з хостів, а не тільки з DNS‑серверів.
- Майте відому командну добірку для on‑call:
getent,resolvectl,journalctl,tcpdump.
FAQ
1) Чи варто вимкнути systemd-resolved, щоб виправити повільний DNS?
Зазвичай — ні. Вимкнення часто ламає split DNS, маршрутизацію VPN і консистентну поведінку між додатками. Виправляйте реальний вузький місце (search‑домени, неправильний per‑link DNS, таймаути) та зберігайте рушій політики.
2) Чому в /etc/resolv.conf є 127.0.0.53?
Це локальний stub‑резольвер systemd‑resolved. Додатки питають localhost; resolved пересилає до справжніх DNS‑серверів і застосовує маршрутизацію/кеш. Якщо він повільний — або пересилання повільне, або він виконує зайву роботу для кожного запиту.
3) Чому dig швидкий, а getent повільний?
dig — це DNS‑клієнт; getent проходить NSS і використовує той же шлях, що більшість додатків. Повільний getent зазвичай означає, що порядок NSS, search‑домени або інтеграція resolved спричиняють додаткові запити або таймаути.
4) Як визначити, що затримка викликана розгортанням search‑доменів?
Дивіться дебаг‑логи resolved і пакетні захвати. Ви побачите повторні запити для одного базового імені з різними суфіксами. Також порівняйте одно‑мітковий lookup (db) і FQDN (db.corp.example).
5) Чи робить DNSSEC запити повільними?
Може, але це не винуватець за замовчуванням. Більшість накладних витрат DNSSEC невеликі. Затримки з’являються, коли валідація викликає додаткові запити, час синхронізації неправильний або upstream ланцюг поламаний. Визначайте політику явно замість надії на дефолти.
6) Чи може IPv6 викликати «повільний DNS», навіть якщо DNS в порядку?
Так. Багато додатків спочатку резолвлять AAAA і потім пробують IPv6. Якщо IPv6‑зв’язність зламана, затримка з’єднання може помилково виглядати як затримка DNS. Розділяйте час розв’язання (getent) і час встановлення з’єднання (curl -v або nc).
7) Який найбезпечніший спосіб змінювати налаштування резольвера на серверах?
Змінюйте їх через системний мережевий менеджер і зберігайте як код (конфіги netplan, профілі NetworkManager або unit‑и systemd‑networkd). Уникайте одноразових правок /etc/resolv.conf.
8) У мене кілька DNS‑серверів. Чому це може бути повільніше?
Якщо один сервер мертвий або відкидає відповіді, резольвер може чекати, повторювати, потім переключатися. Це додає секунди. Кілька серверів корисні, коли вони здорові; вони жахливі, коли один тихо зламаний.
9) Чому NXDOMAIN інколи довше, ніж успішна відповідь?
Бо резольвер може пробувати search‑домени і декілька типів записів, і деякі upstream‑сервери таймаутять замість коректної відповіді для певних суфіксів. Негативні відповіді повинні бути швидкими; якщо ні — десь щось неправильно маршрутизовано або зламано.
Наступні кроки, які можна зробити сьогодні
Зробіть три речі, у цьому порядку:
- Виміряйте через
getent ahostsіresolvectl query, щоб налагоджувати той самий шлях, що і ваші додатки. - Зробіть ланцюжок резольвера нудним: адекватний порядок
hosts:, короткі списки search, коректна per‑link DNS‑маршрутизація і жодної війни за/etc/resolv.conf. - Коли бачите секунди — збирайте докази: дебаг‑логи resolved і короткий
tcpdump. Потім виправляйте реальну причину — мертві резольвери, неправильні маршрути, MTU/EDNS‑зломи — замість прикривання проблем.
Коли DNS стане швидким і передбачуваним, інша частина вашої системи перестане виглядати «примарною». Це й є суть reliability engineering: менше загадок, більше сну.