DNS
Навіщо це
Section titled “Навіщо це”Сайт не відкривається, а ping 192.0.2.10 проходить. Або інакше: ви перенесли
сайт на новий сервер, змінили запис, а половина користувачів ще годину ходить
на старий. Або: у контейнері curl чекає п’ять секунд, перш ніж з’єднається, і
жодних помилок у лозі нема.
Усі ці історії про одну систему, і в ІТ про неї є приказка: «це завжди DNS». Жарт тримається на тому, що DNS стоїть перед майже кожним з’єднанням, кешується на п’яти рівнях і збоїть мовчки. Після цього модуля ви зможете показати, на якому саме кроці розв’язання зупиняється ім’я, і пояснити, чому інша людина бачить іншу відповідь.
Передумови. UDP, TCP і порти (модуль 11), адреси (модуль 6).
Вміти запустити dig (пакет bind9-dnsutils у Debian і Ubuntu, bind-utils у сімействі Red Hat).
Навіщо імена і як їх колись розв’язували
Section titled “Навіщо імена і як їх колись розв’язували”Люди запам’ятовують імена, а маршрутизатори працюють з адресами. Потрібна таблиця
відповідності, і в ранній мережі вона була буквально таблицею: один файл HOSTS.TXT,
який вів єдиний центр, а всі вузли періодично його завантажували. Поки вузлів були
сотні, це працювало. Коли їх стало тисячі, файл розрісся, його доводилося
скрізь оновлювати, а змінити навіть один рядок міг лише центр.
DNS, запропонований на початку 1980-х, розв’язав це не кращим файлом, а іншою будовою: розподіленою базою з делегуванням. Кожен власник домену сам тримає свою частину даних, а щоб знайти чужу, ніхто не мусить мати копію всього. Ця ідея (ієрархія, кеш, делегування) працює понад сорок років.
Файл теж нікуди не подівся: /etc/hosts живий досі й, як побачимо, має пріоритет.
Ієрархія і делегування
Section titled “Ієрархія і делегування”Ім’я читається справа наліво. У www.example.com. кінцева крапка позначає
корінь, далі com, далі example, далі www. Кожен шматок між крапками
називається міткою (label). Мітка може мати до 63 байтів, а все ім’я в текстовому
вигляді не довше за 253 символи.
Це дерево, і кожна його гілка може належати іншій організації.
- Корінь (root) — вершина. За ним стоять 13 імен серверів (від
a.root-servers.netдоm.root-servers.net), але це лише імена: кожне обслуговують багато фізичних серверів у різних країнах за однією адресою (anycast). - Домени верхнього рівня (TLD):
com,org,ua,de. Їх утримують реєстри. - Домени нижче:
example.comналежить тому, хто його зареєстрував, і він сам вирішує, що лежить усередині.
Домен і зону (zone) легко сплутати. Домен охоплює піддерево імен, а зона —
лише ту частину дерева, що описана в одному файлі даних і обслуговується одними серверами. Коли власник
example.com вирішує віддати dev.example.com іншій команді, він делегує піддомен:
додає у свою зону записи NS, які кажуть, «за цим піддеревом іди до таких-то серверів».
Відтепер dev.example.com — окрема зона, а батьківська її вміст не знає.
Записи NS у батьківській зоні іноді потребують ще й адреси: якщо сервери
dev.example.com самі називаються ns1.dev.example.com, то, щоб їх знайти, треба
спершу знайти їх ім’я, а для цього вже треба сервер. Вирішує це glue-запис: у батьківській
зоні поруч із NS лежить і адреса, яку віддають у відповіді як «додаткову».
Сервер, що відповідає за зону зі своїх даних, називається авторитетним (authoritative).
У його відповіді стоїть прапорець aa. Достеменно відповідь знає лише
він, решта тільки кешує чи переказує.
Хто бере участь у запиті
Section titled “Хто бере участь у запиті”У розв’язанні імені задіяні різні ролі, і їх часто плутають.
- Stub-резолвер живе у вашій програмі чи ОС як крихітна частина бібліотеки. Він не вміє
ходити ієрархією, лише спитати одного знайомого сервера і прийняти відповідь.
Адреса цього сервера записана в
/etc/resolv.conf. - Рекурсивний резолвер (recursive resolver) бере на себе всю роботу: ходить від кореня вниз, збирає відповідь, кешує й віддає її клієнту. Його тримають провайдер, організація або публічний сервіс, а на домашньому роутері це зазвичай пересилач до провайдерського.
- Авторитетний сервер — остаточне джерело для своєї зони. Сам нікуди не ходить і кешем не користується.
Для кожної ролі є свої програми: Unbound і Knot Resolver рекурсивні, NSD і Knot DNS авторитетні, а BIND уміє обидві. Поєднувати їх на одному публічному сервері не радять: рекурсія, відкрита для всього інтернету, стає знаряддям DDoS-підсилення. Авторитетний сервер має відповідати лише про свою зону й нікому не робити рекурсію.
Одне ім’я з порожнім кешем коштує чотирьох обмінів по мережі. Кеш у DNS —
умова існування, а не оптимізація: без нього корінь утонув би за першу хвилину. З теплим кешем про корінь і com резолвер майже
ніколи не питає, бо їхні NS живуть у кеші добу й довше.
Повідомлення і транспорт
Section titled “Повідомлення і транспорт”Запит і відповідь мають однаковий формат: заголовок, питання (ім’я, тип, клас), а далі три секції записів: відповідь, авторитетні (authority) і додаткові (additional). У заголовку найцікавіші прапорці:
| Прапорець | Значення |
|---|---|
qr |
це відповідь, а не запит |
aa |
відповідає авторитетний сервер |
rd |
клієнт просить рекурсію (recursion desired) |
ra |
сервер її підтримує (recursion available) |
tc |
відповідь обрізана й не влізла в датаграму |
ad |
дані перевірено через DNSSEC |
і код результату RCODE: NOERROR (усе гаразд), NXDOMAIN (такого імені немає),
SERVFAIL (сервер не зміг відповісти: недоступні авторитетні, збій перевірки підпису),
REFUSED (сервер не хоче відповідати саме вам).
Окремий випадок: NOERROR з порожньою секцією відповіді. Ім’я існує, але запису запитаного
типу нема (наприклад, AAAA для хоста, що має тільки A). Це NODATA, і це не
NXDOMAIN.
Транспорт. Звичайний запит іде за UDP на порт 53: одна датаграма туди, одна
назад, без рукостискання (тому DNS і було створено на UDP, див. модуль 11).
Якщо відповідь не влізла, сервер ставить прапорець tc і відправляє скільки влізло.
Клієнт, побачивши tc, повторює запит за TCP на той самий порт. Це легко побачити, якщо
змусити сервер віддати велику відповідь і вимкнути розширення, що збільшує ліміт
(+noedns: тоді ліміт класичні 512 байтів):
dig @10.0.0.13 big.example.test TXT +noedns +ignore | grep flagsdig @10.0.0.13 big.example.test TXT +noedns | grep -E "SERVER|MSG SIZE";; flags: qr aa tc rd ad; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0;; SERVER: 10.0.0.13#53(10.0.0.13) (TCP);; MSG SIZE rcvd: 850Перша команда з +ignore не повторює запит і показує tc. Друга повторює сама, і видно,
що справжню відповідь (850 байтів) отримано вже за TCP. Сучасні клієнти за замовчуванням
користуються механізмом EDNS0, який дозволяє оголосити більший розмір UDP-датаграми (у повному
виводі dig це рядок EDNS: ... udp: 1232), тому tc трапляється рідше, але не зник. Так
само за TCP ходять перенесення зон між серверами й великі відповіді з DNSSEC.
Файрвол, який пропускає лише UDP 53 і блокує TCP 53, зламає DNS вибірково, лише для великих відповідей. Діагностувати таке важко: більшість запитів працює.
Кеші й TTL
Section titled “Кеші й TTL”Кожен запис у відповіді несе TTL (time to live), число секунд, протягом яких його
дозволено тримати в кеші. Резолвер відраховує його вниз, і це видно на власні очі:
перший запит до резолвера дає 300, другий через три секунди — 297.
dig @127.0.0.1 www.example.test;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1www.example.test. 300 IN CNAME web.example.test.web.example.test. 300 IN A 192.0.2.10web.example.test. 300 IN A 192.0.2.11# повторний запит через 3 секунди:www.example.test. 297 IN CNAME web.example.test.web.example.test. 297 IN A 192.0.2.11web.example.test. 297 IN A 192.0.2.10Прапорця aa немає, бо відповідь прийшла з кешу резолвера. А порядок адрес змінився: сервер навмисно ротує записи, що дає
найпростіший розподіл навантаження (DNS round-robin).
З цього випливає головна властивість DNS: зміна запису не діє, доки не скінчиться TTL у чужих кешах. Експеримент: запис із TTL 5 секунд, який змінюють на авторитетному сервері.
резолвер, до зміни: fast.example.test. 5 IN A 192.0.2.50авторитетний, після зміни: 192.0.2.51резолвер, одразу після: fast.example.test. 2 IN A 192.0.2.50 ← старерезолвер, за 5 с: fast.example.test. 5 IN A 192.0.2.51 ← новеАвтор запису не може «скасувати» те, що вже лежить у чужих кешах, тож перед плановим перенесенням сайту TTL зменшують (скажімо, до хвилини) заздалегідь, щонайменше на стару величину TTL раніше, і підіймають назад після. Навпаки, TTL у добу означає, що помилку в записі виправлятимуть добу.
Негативне кешування
Section titled “Негативне кешування”Кешується й відсутність відповіді: інакше кожен запит до неіснуючого імені
доходив би до авторитетного сервера. Тривалість негативного кешу береться із запису
SOA зони: менше з TTL самого SOA і його останнього поля (minimum).
Зона example.test у нашому експерименті має SOA з TTL 300 і minimum 60:
example.test. 60 IN SOA ns1.example.test. hostmaster.example.test. 2026093001 3600 600 86400 60Резолвер віддав відповідь NXDOMAIN із SOA у секції authority і TTL 60, а за
дві секунди повторив її з TTL 58. Звідси знайома ситуація: створили запис для щойно
вигаданого імені, відкрили сторінку, побачили помилку, додали запис, а помилка не зникає
ще хвилину (чи годину, залежно від minimum), бо в кеші лежить «нема».
Поля SOA загалом: головний сервер зони, пошта відповідального (першу крапку читають як @),
серійний номер (його збільшують за кожної зміни, щоб вторинні сервери помітили), інтервали
оновлення, повтору й закінчення для вторинних серверів і те саме minimum.
Кешів більше, ніж один
Section titled “Кешів більше, ніж один”Між вами і авторитетним сервером кешують майже всі: браузер, бібліотека в процесі,
локальна служба на кшталт systemd-resolved, роутер, рекурсивний резолвер
провайдера. Тому колеги й бачать інакше, ніж ви: у кожного своя гілка кешів із
власною датою народження. Командою dig зі вказаним сервером (@адреса) ви
обходите всі локальні шари і питаєте саме цей рівень.
Типи записів
Section titled “Типи записів”Запис складається з імені, TTL, класу (завжди IN), типу й даних. Типи, що
траплятимуться найчастіше:
| Тип | Що містить | Приклад |
|---|---|---|
A |
IPv4-адреса | web A 192.0.2.10 |
AAAA |
IPv6-адреса | web AAAA 2001:db8::10 |
CNAME |
псевдонім, інше ім’я | www CNAME web |
MX |
поштовий сервер і пріоритет (менше — важливіше) | @ MX 10 mail |
NS |
авторитетний сервер зони чи делегування | @ NS ns1 |
SOA |
службові параметри зони | див. вище |
TXT |
довільний текст: SPF, підтвердження власності | @ TXT "v=spf1 -all" |
PTR |
ім’я за адресою, зворотне розв’язання | 10.2.0.192.in-addr.arpa. PTR web.example.test. |
SRV |
хост і порт сервісу, пріоритет, вага | _sip._tcp SRV 10 5 5060 sip |
CAA |
які центри сертифікації можуть видавати сертифікат для домену | @ CAA 0 issue "letsencrypt.org" |
Запуск dig з типом після імені показує кожен із них. Вивід із нашої лабораторної зони:
example.test. 300 IN MX 10 mail.example.test.example.test. 300 IN TXT "v=spf1 -all"example.test. 300 IN CAA 0 issue "letsencrypt.org"_sip._tcp.example.test. 300 IN SRV 10 5 5060 sip.example.test.10.2.0.192.in-addr.arpa. 300 IN PTR web.example.test.Кілька правил, об які спотикаються першими.
CNAME— це не перенаправлення, а синонім. Ім’я зCNAMEне може мати жодних інших записів, томуCNAMEне ставлять на вершині зони (example.comсам мусить матиNSіSOA). Резолвер бачитьCNAME, далі розв’язує цільове ім’я і віддає ланцюжок, як у виводі вище.PTR— у власному дереві. Адреса192.0.2.10записується задом наперед як10.2.0.192.in-addr.arpa.Власник блоку адрес (провайдер) делегує зворотну зону тому, кому віддав адреси. ТомуPTRчасто відсутній або не збігається зA.MXвказує на ім’я, не на адресу, і те ім’я не може бутиCNAME.SRVдозволяє не вшивати порт у клієнта. Клієнт питає_sip._tcp.домені отримує хост, порт і пріоритет. Ім’я починається з підкреслень, бо це службові мітки.
Як застосунок розв’язує ім’я
Section titled “Як застосунок розв’язує ім’я”Програма розв’язує ім’я викликом getaddrinfo() з бібліотеки C. Той спершу
звіряється зі списком у /etc/nsswitch.conf:
hosts: files dnsСпершу files (/etc/hosts), тоді dns. Тому запис у /etc/hosts завжди виграє
і є найзручнішим способом «підмінити» ім’я локально для перевірки. Але тут же
й пастка:
getent hosts pinned.example.test # іде за nsswitch: знайде в /etc/hostsdig pinned.example.test +short # питає лише DNS: нічого192.0.2.77 pinned.example.test(порожньо)dig не користується nsswitch.conf і /etc/hosts. Якщо ping бачить
ім’я, а dig ні (чи навпаки), причина майже завжди тут. Щоб побачити те, що бачить програма,
користуйтеся getent hosts.
Другий файл — /etc/resolv.conf, де записано, кого питати:
nameserver 127.0.0.1search example.testoptions timeout:2 attempts:2nameserver— адреса рекурсивного резолвера (використовуються перші три); якщо перший мовчить, бібліотека чекаєtimeout(за замовчуванням 5 с) і пробує наступний, звідси ті самі «п’ять секунд перед з’єднанням».search— домени, які дописуються до неповного імені. Томуgetent hosts webзнайдеweb.example.test, аdig webбез+searchпитає проweb.і отримуєNXDOMAIN.options ndots:N— скільки крапок має мати ім’я, щоб його спершу спробували як повне, а вже потім ізsearch. У контейнерних середовищах туди часто ставлятьndots:5, і тоді розв’язання короткого зовнішнього імені проходить кілька марних запитів із доданими доменами, перш ніж дійде до справжнього.
Безпека: DNSSEC, DoT і DoH
Section titled “Безпека: DNSSEC, DoT і DoH”Класичний DNS не має ні автентичності, ні таємності. Відповідь можна підробити на шляху або отруїти кеш резолвера (знаменита атака Дена Камінськи 2008 року), а запити видно кожному, хто бачить трафік. Ці дірки закривають окремі інструменти.
DNSSEC відповідає за автентичність. Власник зони підписує свої записи ключем,
і підпис лежить поруч у записах RRSIG, а відкритий ключ у DNSKEY. Довіряти
ключу зони можна тому, що батьківська зона публікує його хеш у записі DS, а батьківську
перевірено так само вище, аж до кореня, чий ключ резолвер знає заздалегідь. Це
ланцюг довіри, що йде вниз по тій самій ієрархії делегування. Валідуючий резолвер
перевіряє ланцюг і ставить у відповіді ad; якщо підпис не сходиться, клієнт
отримує SERVFAIL. DNSSEC не шифрує нічого: запити й відповіді лишаються відкритими,
а гарантовано лише те, що їх не підмінили.
DoT (DNS over TLS) і DoH (DNS over HTTPS) відповідають за таємність на ділянці клієнт → резолвер. DoT обгортає звичайний DNS у TLS на окремому порту (853), DoH вкладає його в HTTPS на порту 443, де він маскується під звичайний веб-трафік. Обидва ховають запити від тих, хто бачить канал, але резолвер бачить усе, а ділянка резолвер → авторитетні сервери лишається відкритою. Тому вибір резолвера — це вибір того, кому ви довіряєте свою історію імен. (Про TLS — модуль 15.)
Ще одну сучасну практику видно прямо в нашому захопленні нижче:
мінімізацію імені запиту (QNAME minimization). Резолвер не розкриває корінню повне ім’я
www.example.com, а питає лише про те, що цьому серверові потрібно знати: у корінь
іде питання про com, а не про весь хост.
Як це насправді в Linux
Section titled “Як це насправді в Linux”Лабораторний стенд для цього розділу — три авторитетні сервери BIND у просторі імен
srv (корінь 10.0.0.11, зона test на 10.0.0.12, зона example.test на
10.0.0.13) і рекурсивний резолвер Unbound у просторі імен cli. Власний корінь
дозволяє повторити все без інтернету; у лабораторній B5
ви збудуєте схожий.
dig і його ключі
Section titled “dig і його ключі”dig web.example.test # A за замовчуванням, резолвер із resolv.confdig @10.0.0.13 web.example.test # спитати конкретний серверdig web.example.test +short # лише даніdig example.test MX # тип записуdig -x 192.0.2.10 # зворотне розв'язання (PTR)dig +tcp web.example.test # примусово TCPdig +norecurse @10.0.0.13 example.test NS # не просити рекурсіюУ виводі читайте заголовок (status, прапорці), секцію відповіді
(число ANSWER у заголовку) і Query time із SERVER внизу: чия саме це відповідь.
dig +trace
Section titled “dig +trace”+trace не питає резолвер: dig сам повторює роботу рекурсивного резолвера, крок за кроком,
і друкує кожну ланку делегування. Це найкращий спосіб довідатися, на якому рівні
зламалося: корінь не знає TLD, TLD вказує на мертвий сервер, авторитетний відповідає інакше,
ніж очікувалося.
dig +trace +nodnssec @10.0.0.11 www.example.test A. 86400 IN NS a.root.test.;; Received 96 bytes from 10.0.0.11#53(10.0.0.11) in 0 ms
test. 86400 IN NS ns.test.;; Received 110 bytes from 10.0.0.11#53(a.root.test) in 0 ms
example.test. 86400 IN NS ns1.example.test.;; Received 107 bytes from 10.0.0.12#53(ns.test) in 4 ms
www.example.test. 300 IN CNAME web.example.test.web.example.test. 300 IN A 192.0.2.10web.example.test. 300 IN A 192.0.2.11example.test. 300 IN NS ns1.example.test.;; Received 157 bytes from 10.0.0.13#53(ns1.example.test) in 0 msТри переходи: корінь відсилає до test, сервер test до example.test, і лише
останній дає відповідь. Зверніть увагу, що в рядку Received завжди вказано, хто
щойно відповів. На справжньому інтернеті вивід довший: першим іде перелік усіх
тринадцяти кореневих серверів, а при DNSSEC (без +nodnssec) додаються рядки
RRSIG і DS.
Що відбувається по мережі
Section titled “Що відбувається по мережі”У просторі імен srv слухаємо порт 53, а з cli питаємо резолвер із порожнім кешем
про web.example.test, двічі:
ip netns exec srv tcpdump -nn -i v1 'port 53'10.0.0.2.48359 > 10.0.0.11.53: 33248% [1au] NS? . (28)10.0.0.11.53 > 10.0.0.2.48359: 33248*- 1/0/2 NS a.root.test. (68)10.0.0.2.45316 > 10.0.0.11.53: 57965% [1au] A? test. (33)10.0.0.11.53 > 10.0.0.2.45316: 57965- 0/1/2 (66)10.0.0.2.12915 > 10.0.0.12.53: 62830% [1au] A? example.test. (41)10.0.0.12.53 > 10.0.0.2.12915: 62830- 0/1/2 (75)10.0.0.2.57650 > 10.0.0.13.53: 41709% [1au] A? web.example.test. (45)10.0.0.13.53 > 10.0.0.2.57650: 41709*- 2/1/2 A 192.0.2.11, A 192.0.2.10 (111)Вісім пакетів, чотири запити й чотири відповіді: та сама діаграма, що на
рисунку. Кожен запит іде з нового випадкового порту, а не з порту 53:
у поєднанні з випадковим 16-бітним ідентифікатором це ускладнює підробку відповіді.
І питання до кореня й TLD стосуються лише test. та example.test., тобто видно
мінімізацію імені. Другий такий самий запит до резолвера не створив жодного пакета:
усе з кешу.
Діагностика в п’ять кроків
Section titled “Діагностика в п’ять кроків”getent hosts імʼя: що бачить програма. Порожньо, аdigзнаходить? Дивіться/etc/hosts,nsswitch.conf,search.dig імʼя: що каже резолвер ізresolv.conf. Перевіртеstatus,ra, TTL.dig @8.8.8.8 імʼячи інший публічний резолвер: чи збігається з вашим. Різні відповіді означають різні кеші чи підміну на шляху.dig +trace імʼя: що кажуть самі авторитетні сервери. Тут видно делегування, мертвий NS, розбіжність між серверами зони.dig @<авторитетний> імʼядля кожного NS: однакова відповідь? Якщо серійні номериSOAрізні, вторинний сервер відстав від первинного.
Чому «це завжди DNS»
Section titled “Чому «це завжди DNS»”За жартом стоять цілком реальні механізми, і всі вони вже траплялися в цьому модулі:
- Кеші з TTL: зміна не діє всюди одразу, а виправлена помилка ховається за негативним кешем.
- Кілька шарів кешу, і кожен із власним віком, тому різні користувачі бачать різне.
- Резолвер із першого рядка
resolv.confне відповідає, і кожен запит чекає таймаут. Програма «зависає» на секунди, а то й десятки секунд, без жодного повідомлення. searchіndotsперетворюють одне ім’я на кілька запитів.- Обрізані відповіді й заблокований TCP 53 ламають лише великі відповіді.
AAAAє, а IPv6 не працює: клієнт чекає на адресу, що ніколи не відповість (про це модуль 10).- Різні відповіді зсередини й ззовні (split-horizon), заплановані, але забуті.
- Розходження між NS: один із серверів зони віддає застарілі дані, а запити розподіляються між ними довільно, і помилка стає «плаваючою».
Є ще й психологічний ефект: коли ламається DNS, падає все одразу, і причину шукають усюди, крім нього, бо саме DNS не пише в лог нічого підозрілого.
Типові помилки розуміння
Section titled “Типові помилки розуміння”«Зміна запису розійдеться по світу за кілька годин (propagation)». Ніякого розсилання нема. Резолвери самі питають і кешують на TTL. Нове значення «з’являється» у кожного резолвера в момент, коли в нього протухає старе, тобто не пізніше ніж за TTL після зміни (плюс негативний кеш, якщо запису раніше не було).
«dig показує те, що бачить моя програма». dig питає DNS напряму й не читає
/etc/hosts та nsswitch.conf. Те, що бачить програма, покаже getent hosts.
«DNS працює по UDP». Здебільшого так, але не лише: обрізані відповіді (а з DNSSEC вони трапляються частіше) і перенесення зон ідуть за TCP, а DoT і DoH працюють поверх TLS. Мережа, що блокує TCP 53, ламає DNS частково.
«DNSSEC шифрує DNS». Він лише підписує: підробку видно, але запити ніхто не ховає. Таємність дають DoT і DoH, а вони не підтверджують правдивості відповіді.
«CNAME — це перенаправлення на інший сайт». Це псевдонім імені в DNS: клієнт
усе одно підключається за адресою цільового імені й відправляє початкове ім’я
у своєму HTTP-запиті. Жодних перенаправлень на рівні HTTP тут нема.
«Кореневих серверів тринадцять». Тринадцять імен, за якими стоять сотні екземплярів на всіх континентах. Адреси однакові, а маршрутизація доставляє до найближчого (anycast).
Перевір себе
Лабораторна
Section titled “Лабораторна”- A5. Ітеративний DNS-резолвер: розбір формату повідомлення, хід від
кореня вниз по делегуваннях, кеш із TTL: усе, що ви бачили в
dig +traceі в захопленні. - B5. Власні DNS і TLS: авторитетна зона, рекурсивний резолвер і
перевірка
dig +traceу власній ієрархії.
Джерела
Section titled “Джерела”- Kurose, Ross, Computer Networking: A Top-Down Approach, розділ про DNS
- Peterson, Davie, Computer Networks: A Systems Approach, розділ про іменування
- Liu, Albitz, DNS and BIND (O’Reilly)
- RFC 1034 і RFC 1035: основа DNS; RFC 2308 (негативне кешування)
- RFC 4033, 4034, 4035 (DNSSEC); RFC 7858 (DoT); RFC 8484 (DoH)
man 1 dig,man 5 resolv.conf,man 5 nsswitch.conf,man 1 getent,man 1 resolvectl- Документація Unbound і BIND 9