Піки навантаження DNS: лімітування запитів і переживання атак без простоїв

Було корисно?

DNS — це та залежність, про яку всі забувають, доки вона не загориться. Ваш веб‑рівень може автоскейлитись, кеші можуть поглинати навантаження, бази даних — скидати навантаження. DNS? DNS просто відповідає на запити, поки не перестає — і тоді все виглядає «невключеним», хоча сервери в порядку.

Піки навантаження б’ють по DNS некрасиво: раптова популярність, зламані клієнтські повтори, сканування ботів, NXDOMAIN‑флуди, рефлексні атаки або «корисна» зміна, що перетворює тиху зону на хаос. Фокус не просто в блокуванні трафіку. Потрібно обмежувати правильні речі, на правильному рівні, не обманюючи легітимних клієнтів і не створюючи власних збоїв.

Що саме ламається під час піків DNS

Коли DNS падає, ви зазвичай не отримуєте чіткої тривоги «DNS не працює». Ви бачите парад вторинних симптомів: проблеми з логіном, випадкові таймаути API, «флапінг» вузлів Kubernetes і CEO, який не може зайти на маркетинговий сайт (який, на жаль, стає «P0»).

Режим відмови 1: обробка пакетів падає раніше за CPU

Більшість DNS‑демонів швидкі, але їм потрібне ядро для отримання пакетів, чергування та доставки в простір користувача. Під хвилеподібним QPS ви можете вдаритися в:

  • виснаження кілець NIC (скиди на драйвері).
  • переповнення буферів сокета для прийому (скиди в ядрі).
  • вузькі місця однопотокового виконання (демон не встигає обробляти черги).

Результат: клієнти бачать таймаути і повторюють запити, що множить трафік і перетворює «спайк» у «спіраль». DNS — одне з небагатьох місць, де «таймаут» не просто симптом — це підсилювач трафіку.

Режим відмови 2: затримка вбиває вас задовго до помилок

Клієнти DNS часто чекають лише кілька сотень мілісекунд перед повтором або переключенням. Сервер ще може відповідати, але якщо p95 повзе з 5 мс до 200 мс, ви побачите «випадкові» збої в додатках.

Режим відмови 3: перемагає неправильний трафік

Не всі запити заслуговують однакового ставлення. Під час атак ви отримаєте потоки таких запитів:

  • випадкові піддомени (наприклад, asdf123.example.com), створені щоб обійти кеші й викликати роботу NXDOMAIN або NODATA.
  • запити типу ANY (менш актуально зараз, але все ще трапляється) або типи, що породжують великі відповіді.
  • EDNS‑запити, які намагаються отримати великі UDP‑відповіді для рефлексії.

Якщо ваша інфраструктура ставиться до цього як до нормального трафіку, ви захищаєте кількість запитів нападника, а легітимні клієнти стоять у черзі за ними. Це не нейтральність — це операційне самошкодування.

Режим відмови 4: ваша «захисна міра» — це відмова сервісу

Неправильно зроблене лімітування не відрізняється від атаки. Занадто жорстко — ви відрізаєте реальних користувачів за NAT чи CGNAT. Надто хитро — ви душите власні рекурсивні резолвери або health check’і. Мета — контрольоване деградування: частина відповідей може сповільнюватися або обриватися, але сервіс залишається доступним і швидко відновлюється.

Одне сухе зауваження: DNS — це місце, де «прості» конфігурації перетворюються на розподілені системи. Ви ведете переговори з stub‑резолверами, рекурсивними резолверами, кешами, middlebox‑ами і людьми з застарілою прошивкою в готельних Wi‑Fi роутерах.

Цитата для запам’ятовування (перефразована ідея): «Сподівання — це не стратегія», часто кажуть інженери та оператори, що працюють над надійністю. Ставтеся до піків DNS так само: проектуйте, вимірюйте, репетируйте.

Жарт #1: DNS — єдина система, де найкращий результат — бути проігнорованим, бо всіх все закешували.

Цікаві факти й історичний контекст

  • DNS передував сучасному вебу: його спроектували на початку 1980‑х, щоб замінити модель розповсюдження HOSTS.TXT.
  • UDP був вибраний за замовчуванням для швидкості: DNS по UDP уникало встановлення з’єднання, що добре, поки не зустрінеш підробки адрес і рефлексивні зловживання.
  • Кешування DNS — це навмисне зниження навантаження: TTL — не лише механізм коректності; це економічна система для QPS.
  • Система root‑серверів — не одна коробка: це глобальна anycast‑констеляція; «root впав» майже завжди означає локальну проблему.
  • Запити ANY стали інструментом DDoS: багато операторів зараз мінімізують або обмежують відповіді на ANY, бо їх використали для створення надвеликих відповідей.
  • DNSSEC збільшив розміри відповідей: додавання підписів покращує цілісність, але може погіршити фрагментацію та ризик підсилення, якщо не керувати EDNS‑розмірами.
  • Response Rate Limiting (RRL) з’явився з болю: авторитетним операторам потрібен був спосіб зменшити корисність рефлексії, не звалившись у офлайн.
  • NXDOMAIN‑атаки старі: флуди випадкових піддоменів використовують роками, бо вони обходять звичайне кешування.
  • Anycast змінив підхід: рознесення авторитетного DNS по POP‑ах знижує насичення одного сайту, але додає складності налагодження.

План швидкої діагностики (перший/другий/третій)

Це послідовність «припини вгадувати». Ви можете виконати її за 10 хвилин, поки всі інші сперечаються в Slack.

Перший: підтвердьте, що це саме DNS, а не «щось, що виглядає як DNS»

  1. З мережі постраждалого клієнта опитайте прямо ваш авторитетний нейм‑сервер (обійдіть рекурсію). Перевірте затримки та таймаути.
  2. Зсередини дата‑центру/VPC зробіть те саме. Якщо у внутрішній мережі все добре, а зовні — ні, підозрюйте насичення на краї або зовнішнє фільтрування.
  3. Перевірте, чи спайк стосується авторитетного, рекурсивного чи обох. Вони падають по‑різному.

Другий: знайдіть шар з вузьким місцем

  1. Вхід у мережу: скиди на NIC/ядрі, conntrack‑бурі, PPS‑обмеження.
  2. Демон: CPU на потік, контенція замків, хвилі пропусків кешу, витрати на DNSSEC‑підписування/валідацію.
  3. Бекенд‑залежності: динамічні бекенди (БД), повільні зони‑трансифери, перевантажені логування або телеметрія.

Третій: застосуйте безпечне утримання, потім оптимізуйте

  1. Розгорніть лімітування на краї (dnsdist / фаєрвол / load balancer), перш ніж чіпати внутрішні налаштування демона.
  2. Пріоритезуйте: збережіть базові A/AAAA/CNAME/SOA/NS; деградуйте «приємні, але необхідні» (ANY, TXT, великі відповіді).
  3. Спочатку стабілізуйте затримку (p95). Потім уже ганяйте абсолютний QPS.

Спочатку виміряйте: завдання, команди, виходи, рішення

Ви не зможете вийти з лімітування, якщо не знаєте, що відбувається. Нижче — практичні завдання, які можна виконати під час інциденту чи репетиції. Кожне містить команду, приклад виходу, що це значить і яке рішення приймати.

Завдання 1: Перевірте авторитетну відповідь і затримку (прямий запит)

cr0x@server:~$ dig @203.0.113.53 www.example.com A +tries=1 +time=1

; <<>> DiG 9.18.24 <<>> @203.0.113.53 www.example.com A +tries=1 +time=1
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43112
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 1
;; ANSWER SECTION:
www.example.com. 60 IN A 198.51.100.10
;; Query time: 12 msec
;; SERVER: 203.0.113.53#53(203.0.113.53) (UDP)
;; WHEN: Tue Dec 31 12:00:00 UTC 2025
;; MSG SIZE  rcvd: 93

Що це означає: Ви отримуєте авторитетну відповідь (флаг aa), із малою затримкою.

Рішення: Якщо це швидко, але користувачі скаржаться, проблема може бути в рекурсії, мережевому шляху або поведінці кешів для негативних відповідей — не в авторитеті.

Завдання 2: Порівняйте поведінку UDP та TCP (виявлення проблем з фрагментацією/EDNS)

cr0x@server:~$ dig @203.0.113.53 example.com DNSKEY +dnssec +time=1 +tries=1

;; Truncated, retrying in TCP mode.
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5321
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; Query time: 210 msec
;; SERVER: 203.0.113.53#53(203.0.113.53) (TCP)

Що це означає: UDP‑усічення змусило повтор по TCP. Під навантаженням TCP дорожчий (стан, accept‑черги, накладні витрати ядра).

Рішення: Налаштуйте EDNS‑розмір буфера і поведінку DNSSEC‑відповідей; розгляньте обмеження великих відповідей і переконайтеся, що обробка TCP забезпечена.

Завдання 3: Перевірте QPS і топ типів запитів на BIND (авторитетний)

cr0x@server:~$ sudo rndc stats
cr0x@server:~$ sudo tail -n 20 /var/cache/bind/named.stats
++ Incoming Requests ++
[View: default]
                          1987632 QUERY
                           504112 NOTIFY
++ Incoming Queries ++
[View: default]
                           912331 A
                           701221 AAAA
                           389002 TXT
                           211332 DNSKEY
                           122880 ANY

Що це означає: У вас великий обсяг TXT/DNSKEY/ANY. Це класичний підпис «зробіть відповіді більшими».

Рішення: Розгляньте звуження політики відповідей: мінімізуйте ANY, лімітуйте типи запитів, що зловживаються, і перегляньте налаштування DNSSEC/EDNS.

Завдання 4: Швидкий огляд статистики Unbound (рекурсивний)

cr0x@server:~$ sudo unbound-control stats_noreset | egrep 'total\.num\.queries|num\.query\.type|unwanted|cache\.hits|cache\.miss|avg\.recursion'
total.num.queries=18422301
num.query.type.A=10233444
num.query.type.AAAA=6012231
num.query.type.TXT=1589222
unwanted.queries=433221
msg.cache.hits=11022334
msg.cache.misses=7401130
avg.recursion.time=0.145000

Що це означає: Кеш‑місси високі, час рекурсії росте. Небажані запити ненульові — ймовірно зловживання або некоректні клієнти.

Рішення: Додайте клієнтське лімітування, ужорсткіть контроль доступу (хто може використовувати рекурсію) і збільште кеш там, де це безпечно. Якщо час рекурсії високий через таймаути upstream, розгляньте форвардінг або доступність root/TLD.

Завдання 5: Визначте топ‑відправників і імена запитів (зразок пакетів)

cr0x@server:~$ sudo tcpdump -ni eth0 udp port 53 -c 50
12:00:01.001234 IP 192.0.2.10.53211 > 203.0.113.53.53: 1234+ A? asdf91k2.example.com. (38)
12:00:01.001260 IP 192.0.2.10.53212 > 203.0.113.53.53: 2234+ AAAA? asdf91k2.example.com. (38)
12:00:01.001289 IP 198.51.100.77.41922 > 203.0.113.53.53: 3321+ ANY? example.com. (28)
...

Що це означає: Випадкові лейбли для вашої зони вказують на NXDOMAIN/NODATA‑флуд, що обходить кеш; запити ANY вказують на проби з ампліфікацією.

Рішення: Застосуйте лімітування за джерелом і за qname/qtype на краї, і розгляньте «синтезовані» мінімальні відповіді там, де це доречно (обережно) або агресивні налаштування негативного кешування.

Завдання 6: Перевірте скиди ядра і помилки прийому UDP

cr0x@server:~$ netstat -su
Udp:
    1283221 packets received
    0 packets to unknown port received
    22111 packet receive errors
    904321 packets sent
    22111 receive buffer errors

Що це означає: Помилки прийому буфера означають, що ядро скидає UDP, бо додаток не встигає обробляти або буфери занадто малі.

Рішення: Збільшіть сокет‑буфери і налаштуйте мережеве ядро; також зменшіть накладні витрати на пакет‑рівні, перемістивши лімітування ближче до краю (dnsdist, XDP, фаєрвол) і зменшіть логування.

Завдання 7: Перевірте скиди на NIC та на рівні ядра

cr0x@server:~$ ip -s link show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    RX:  bytes  packets  errors  dropped overrun mcast
    9876543210 12345678  0       4321    0       0
    TX:  bytes  packets  errors  dropped carrier collsns
    8765432109 11223344  0       0       0       0

Що це означає: RX‑скиди на інтерфейсі вже відбуваються до того, як ваш демон бачить трафік.

Рішення: Додайте потужності (більше інстансів/anycast), використовуйте NIC, що витримують високий PPS, або змусьте upstream фільтрувати/лімітувати, щоб хост не бачив найгіршого.

Завдання 8: Переконайтеся, що conntrack не причетний випадково

cr0x@server:~$ sudo sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max
net.netfilter.nf_conntrack_count = 982312
net.netfilter.nf_conntrack_max = 1048576

Що це означає: Ви близько до максимуму conntrack. DNS по UDP в багатьох дизайнах не потребує conntrack, але фаєрвол/NAT можуть його втягнути.

Рішення: Уникайте stateful‑трекінгу для високого QPS DNS, якщо можливо; перенесіть фільтрацію в stateless правила або на спеціалізовані крайові пристрої, або обережно підніміть ліміти.

Завдання 9: Перевірте стан демона і насичення потоків (systemd + CPU)

cr0x@server:~$ systemctl status named --no-pager
● named.service - BIND Domain Name Server
     Loaded: loaded (/lib/systemd/system/named.service; enabled)
     Active: active (running) since Tue 2025-12-31 11:20:12 UTC; 39min ago
   Main PID: 1023 (named)
      Tasks: 42
     Memory: 1.3G
        CPU: 18min 22.331s
cr0x@server:~$ top -b -n1 | head -n 15
top - 12:00:10 up 10 days,  3:22,  1 user,  load average: 18.21, 17.44, 16.02
%Cpu(s): 92.1 us,  4.1 sy,  0.0 ni,  1.2 id,  0.0 wa,  0.0 hi,  2.6 si,  0.0 st
MiB Mem :  32110.0 total,   2100.0 free,  12000.0 used,  18010.0 buff/cache
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
 1023 bind      20   0  2460.0m  1320.0m   8.1m R  580.0   4.1  18:25.12 named

Що це означає: CPU гарячий; named споживає багато ядер. Якщо затримка все ще погана, CPU не є єдиним вузьким місцем — перевірте скиди і черги.

Рішення: Якщо CPU є лімітером, масштабуйтесь горизонтально і/або зменшуйте дорогі завдання (DNSSEC‑підписування/валідація, логування, динамічні оновлення). Якщо присутні скиди — лімітуйте трафік перед демоном.

Завдання 10: Перевірте розподіл розмірів відповідей DNS (виявлення ризику ампліфікації)

cr0x@server:~$ sudo tcpdump -ni eth0 udp port 53 -vv -c 10
12:00:12.100001 IP 203.0.113.53.53 > 192.0.2.10.53211: 1234 NXDomain 0/1/0 (112)
12:00:12.100120 IP 203.0.113.53.53 > 198.51.100.77.41922: 3321 4/0/6 (1452)

Що це означає: UDP‑відповіді 1452 байти фліртують з фрагментацією (залежно від path MTU). Фрагментація підвищує втрати і може зробити вас кращим інструментом рефлексії.

Рішення: Обмежте EDNS UDP payload (практично ~1232 байти), зменшіть додаткові записи і переконайтеся, що поведінка TC=1 та fallback по TCP прийнятні.

Завдання 11: Перевірте статистику фронтенда dnsdist (крайове лімітування)

cr0x@server:~$ sudo dnsdist -c -e 'showStats()'
aclDrops                                 12345
responses                                9812234
queries                                  9921100
rdQueries                                221001
ruleDrop                                 88321
ruleNXDomain                             0
latency0_1                                7122331
latency1_10                               2501123
latency10_50                              210992
latency50_100                             12012
latency100_1000                            542

Що це означає: Ви відкидаєте трафік через ACL/правила, зберігаючи більшість затримок нижче 10 мс. Це бажана форма під час атаки.

Рішення: Якщо скиди надто великі і страждають легітимні користувачі, уточніть правила (по мережах, по qtype, по qname) замість підняття глобальних лімітів.

Завдання 12: Підтвердіть коректність зони і TTL негативного кешування (SOA)

cr0x@server:~$ dig @203.0.113.53 example.com SOA +noall +answer
example.com. 300 IN SOA ns1.example.com. hostmaster.example.com. 2025123101 7200 3600 1209600 60

Що це означає: Останнє поле (minimum/negative TTL у сучасній практиці) — 60 секунд. Воно визначає, як довго резолвери можуть кешувати NXDOMAIN/NODATA.

Рішення: Під час NXDOMAIN‑флуду занадто низький негативний TTL погіршує ситуацію, бо резолвери перепитують постійно. Підніміть його обдумано (не на дні), до хвилин або години залежно від частоти змін.

Завдання 13: З’ясуйте, чи клієнти надмірно повторюють запити (семплування логів)

cr0x@server:~$ sudo journalctl -u named --since "10 min ago" | egrep 'client|query' | head
Dec 31 11:51:01 ns1 named[1023]: client @0x7f2c1c0a: query (cache) 'asdf91k2.example.com/A/IN' denied
Dec 31 11:51:01 ns1 named[1023]: client @0x7f2c1c0b: query (cache) 'asdf91k2.example.com/AAAA/IN' denied
Dec 31 11:51:01 ns1 named[1023]: client @0x7f2c1c0c: query (cache) 'asdf91k2.example.com/A/IN' denied

Що це означає: Ви бачите повторювані запити для одного випадкового імені, ймовірно від рекурсивних резолверів. Denied означає ACL або рішення лімітування.

Рішення: Якщо легітимні резолвери блокуються — ви занадто близько підрізали. Віддавайте перевагу стратегіям «slip»/усічення або формі по‑джерельному, а не глобальним заборонам.

Завдання 14: Підтвердіть синхронізацію часу (DNSSEC і TTL‑саніті)

cr0x@server:~$ timedatectl
               Local time: Tue 2025-12-31 12:00:30 UTC
           Universal time: Tue 2025-12-31 12:00:30 UTC
                 RTC time: Tue 2025-12-31 12:00:29
                Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
              NTP service: active

Що це означає: Час у порядку. Некоректний час може спричиняти помилки валідації DNSSEC і дивну поведінку кешування.

Рішення: Якщо час не синхронізований — виправте NTP у першу чергу. Діагностика DNS при зсуві часу схожа на діагностику сховища, коли диск уже у вогні.

Шаблони лімітування, що працюють (і чого уникати)

Лімітування DNS — це не «блокувати погані IP». Трафік атаки часто підроблений, розподілений або йде від легітимних рекурсивних резолверів, які самі перевантажені. Ви формуєте систему, де ідентичність клієнта нечітка, а транспорт зазвичай UDP.

Принцип: лімітуйте на краю, а не всередині мозку

Ваш авторитетний демон має витрачати CPU на відповіді легітимним запитам, а не на роль «поліцейського трафіку». Поставте шар попереду:

  • dnsdist для DNS‑свідомої фільтрації та шейпінгу.
  • iptables/nftables для грубих PPS‑лімітів і ACL.
  • anycast + кілька POP щоб перетворити «одну ціль» на багато менших цілей.

Не змушуйте авторитетний сервер парсити й логувати кожен зловмисний запит на рівні debug. Це не спостережливість. Це друкування DDoS на папері.

Шаблон 1: токен‑баґкет на джерело (з урахуванням NAT)

Ліміт за IP QPS — найпростіший контроль. Це також спосіб випадково заблокувати весь мобільний оператор за CGNAT. Використовуйте, але:

  • Встановіть ліміти достатньо високі для великих резолверів.
  • Віддавайте перевагу лімітам за /24 або /56 лише якщо розумієте побічні ефекти.
  • Внесіть у білий список відомі рекурсивні резолвери, на яких ви залежите (ваші власні, великі публічні, якщо доречно).

Шаблон 2: лімітування за патерном qname (флуди випадкових піддоменів)

Випадкові піддомени спрямовані на те, щоб спричинити кеш‑місси. Лімітування за суфіксом qname і «ентропією» може бути ефективним:

  • Тротлінгуйте NXDOMAIN‑відповіді на джерело.
  • Тротлінгуйте запити для «глибоких» міток (наприклад, 20+ символів випадкового префіксу), якщо ваш бізнес їх не використовує.
  • Розгляньте wildcard‑записи обережно — wildcard може перетворити NXDOMAIN у NOERROR, що змінює економіку атаки.

Шаблон 3: мінімізуйте ампліфікаційну цінність

Рефлексивні атаки люблять великі відповіді на малі запити. Зробіть ваш сервер поганим підсилювачем:

  • Мінімізуйте відповіді на ANY (багато авторитетів відповідають мінімально або відмовляють).
  • Обмежуйте EDNS UDP size, щоб зменшити фрагментацію і надмірні відповіді.
  • Уникайте зайвих additional‑записів (glue) без потреби.
  • Переконайтеся, що ви не є відкритим резолвером, якщо ви авторитетний — ця помилка не вмирає.

Шаблон 4: «Slip» (усічення) замість жорсткого блоку, коли це допомагає

Деякі реалізації лімітування можуть «slip»: відправляти усічені відповіді (TC=1) час від часу, щоб легітимні резолвери могли повторити по TCP, а атакуючі втрачали ефективність. Це не магія — TCP теж можна атакувати — але це може перелаштувати витрати на сторону запитувача.

Чого уникати: глобальні QPS‑похили без класифікації трафіку

Глобальний кап каже «я не знаю, що відбувається, тож я нашкоджу всім однаково». Це швидкий спосіб дозволити атаці тривати, поки ваші клієнти йдуть у відтік.

Жарт #2: Єдине страшніше за DNS DDoS — це DNS DDoS плюс «термінове збільшення логування» від когось, хто сумує за 1990‑ми.

Авторитетний vs рекурсивний: різні вороги, різні контролі

Авторитетний DNS: захищайте свої зони й репутацію

Авторитетні сервери відповідають за вашу доменну зону. Атакувальний трафік часто націлений на них, бо вони публічні й передбачувані. Типові зловживання:

  • Рефлексія: підроблені адреси відправника; ваш сервер «атакає» когось іншого.
  • NXDOMAIN‑флуди: випадкові піддомени; ви обчислюєте негативні відповіді знову й знову.
  • DNSSEC‑ампліфікація: великі відповіді типу DNSKEY/DS/NSEC*.

Хороші контролі для авторитетних:

  • RRL (Response Rate Limiting) для схожих відповідей багатьом клієнтам.
  • Правила за типами запитів (наприклад, обмеження ANY, моніторинг TXT/DNSKEY).
  • Розподіл anycast і різноманітний upstream‑транзит.
  • Короткий, адекватний вміст зони (уникайте величезних TXT без потреби).

Рекурсивний DNS: захищайте своїх користувачів і upstream

Рекурсивні резолвери отримують відповіді від інтернету від імені клієнтів. Їх зловживають через:

  • Відкриту рекурсію: сторонні використовують ваш резолвер; ви платите за пропускну здатність і отримуєте скарги.
  • Обхід кешу: випадкові qname змушують запити в upstream і завантажують рекурсію.
  • Шторми повторів клієнтів: неправильно налаштовані додатки або зламані stub‑резолвери.

Хороші контролі для рекурсивних:

  • Контроль доступу: лише ваші мережі можуть використовувати рекурсію.
  • Агресивне кешування там, де безпечно; префетч популярних записів.
  • Лімітування по клієнту і пом’якшення «небажаних запитів».
  • Сервінг прострочених відповідей (serve‑expired) з обережними захисними механізмами, щоб пережити upstream‑відмови.

Пастка: змішувати авторитетний і рекурсивний на одному хості

Так, «працює». Але це також з’єднує домени відмов. Під час атаки ваша рекурсія може виснажити авторитет або навпаки. Тримайте ролі окремими, якщо лише у вас не дуже маленьке середовище й ви полюбляєте ризик.

Проєктування для виживання: архітектура й кроки щодо потужності

Використовуйте anycast, але не боготворіть його

Anycast розподіляє навантаження запитів по кількох сайтах, рекламуючи одну й ту ж IP‑адресу з багатьох локацій. Це індустріальний стандарт для авторитетного DNS у великому масштабі. Також це вводить операційні реалії:

  • Трафік йде за BGP, а не за вашим наміром. Флап маршруту може перемістити половину континенту в один POP.
  • Налагодження «чому цей резолвер потрапляє в той POP?» перетворюється на мережеве завдання.
  • Стан має бути мінімальним: контент зон і ключі повинні правильно реплікуватися.

Впроваджуйте anycast, якщо можете ним керувати добре. Інакше використовуйте кілька unicast NS із сильним upstream‑DDoS‑захистом. Мета надійності — різноманітність.

Виділіть «відповідання» від «обчислення»

Найкращі авторитетні системи роблять мінімум обчислень на запит:

  • Попередньо підписані зони (якщо використовуєте DNSSEC) або ефективна інфраструктура підписування.
  • Дані зони в пам’яті.
  • Жодних синхронних викликів у бази даних на шляху обробки запиту. Якщо вам дуже потрібні динамічні відповіді — фронтуйте їх кешем і строгими «circuit breaker».

Налаштуйте EDNS і розмір UDP свідомо

Великі UDP‑відповіді фрагментуються. Фрагменти скидаються. Скиди фрагментів тригерять повтори. Повтори множать QPS. Ось як ви отримуєте «таємничий» спайк, що виглядає як колективне забування кешування.

Практичний крок: тримайте UDP‑відповіді помірного розміру. Обмежте EDNS UDP payload до консервативного значення; прийміть, що TCP‑fallback іноді необхідний, і проектуйте під нього.

Стратегія TTL: кешування — ваше найдешевше масштабування

Короткі TTL дають відчуття гнучкості. Вони також дорогі. Під час атаки чи вірусного трафіку різниця між TTL 30 і TTL 300 — це фактор 10 у обсязі запитів від резолверів, які дотримуються TTL.

Не встановлюйте TTL на основі відчуттів. Визначайте їх за:

  • Як швидко вам реально потрібно змінювати записи в надзвичайних випадках.
  • Чи маєте ви інші засоби маршрутизації (load balancer, anycast, failover).
  • Вашою терпимістю до кешування застарілих даних під час інцидентів.

Логування: робіть сэмплінг, щоб не потонути

Логування кожного запиту під час спайків — класичне самопошкодження. Використовуйте:

  • Сэмплінг (1 з N запитів).
  • Агреговані метрики (лічильники по qtype, частота NXDOMAIN, топ клієнтів за PPS).
  • Короткі tcpdump‑захоплення з вузькими фільтрами.

Тримайте підсистему зберігання поза зоною ураження. DNS — мережевий сервіс; не перетворюйте його на тест продуктивності диска.

Три корпоративні історії з практики

Міні‑історія 1: інцидент через хибне припущення

Середня SaaS‑компанія тримала авторитетний DNS на двох віртуалках за «надійним» cloud‑load‑balancer’ом. Команда вірила, що балансувальник дає «захист від DDoS за замовчуванням», бо він від великого вендора і мав приємну панель.

Потім партнер інтегрував новий SDK. SDK робив SRV‑lookup при старті додатка для кожного запиту, тому що хтось неправильно прочитав рекомендацію по кешуванню. Це створило цілком легітимний спайк: не атака, а сотні тисяч клієнтів, що були надто активні. Авторитетні сервери зазнали повторюваних запитів, що обходили кеш, бо записи мали TTL 30 секунд «для гнучкості».

Затримки росли. Таймаути збільшувалися. Клієнти повторювали запити. Балансувальник почав чергувати, і врешті health check’і впали, бо DNS‑сервери були зайняті. Балансувальник знів: це сконцентрувало навантаження, що ще більше погіршило ситуацію. Класична позитивна петля з менеджованим сервісом посередині, що додавав таємниці.

Помилка була не в «хмарі ненадійна». Вона була в припущенні, що стандартний балансувальник = DNS‑свідомий край. Вирішили проблему підвищенням TTL, додаванням dnsdist попереду з адекватним шейпінгом на клієнт, розділенням health check’ів від основного шляху запитів. Також написали тест, що симулює паттерн запитів SDK, бо наступний інцидент буде ще дивнішим.

Міні‑історія 2: оптимізація, що повернулася боком

Велика корпоративна мережева команда вирішила «оптимізувати затримки DNS», змусивши всі внутрішні клієнти використовувати невелику групу рекурсивних резолверів в одному дата‑центрі. Вони масштабували резолвери: багато RAM, великі CPU, NVMe для логів. Зміна виглядала добре в тесті для одного офісу.

Через два місяці транзитна проблема погіршила зв’язність цього дата‑центру до кількох TLD‑серверів. Нічого повністю не впало, просто стало повільніше. Час рекурсії збільшився, кеш‑місси стали болючими, і резолвери почали накопичувати беклог. Клієнти — особливо Windows та деякі IoT — агресивно повторювали запити при помилковому відчутті повільності.

Оптимізація створила централізовану домену відмови. Гірше: команда ввімкнула детальне логування запитів, щоби довести покращення, і під час спайків пайплайн логів наситив диск I/O і CPU. Резолвери були повільними не лише через інтернет — вони ще й розповідали про свою біль диск‑операціям.

Вирішення було просте: розподіл рекурсії по регіонах, зниження логування до сэмплінгу/агрегації, увімкнення serve‑expired з обмеженнями, щоб тимчасова повільність upstream не ставала штором повторів клієнтів. Також перестали думати про DNS як про веб‑сервіс, де «одне велике кластерне рішення» завжди вигідне.

Міні‑історія 3: нудна, але правильна практика, що врятувала день

Фінансова компанія тримала авторитетний DNS через anycast у кількох POP. Нічого надзвичайного в зоні — A, AAAA, CNAME, кілька TXT. Нудна частина була в дисципліні: кожна зміна проходила через staging, вони відстежували наміри TTL і квартально репетирували runbook для DDoS.

Одного дня почалася атака: high‑QPS випадкові піддомени плюс TXT і DNSKEY‑проби. Моніторинг підняв різкий ріст NXDOMAIN і помилки прийому UDP в одному POP. On‑call не панікував. Вони дотримувались плейбуку: підтвердили скиди, підтвердили мікс запитів, ввімкнули жорсткіші ліміти для NXDOMAIN, обмежили EDNS‑розмір і тимчасово зменшили пріоритет у BGP для завантаженого POP.

Вплив на клієнтів був мінімальний. Частина резолверів відпала на TCP; деякі запити сповільнились; але домен залишився резольвним. Атака пішла далі, як часто буває, коли ви перестаєте бути цікавою ціллю.

Що врятувало — не якийсь секретний продукт, а виміряні базові лінії, відрепетировані контролі і організаційна повноважність швидко їх застосувати. Рев’ю інциденту було коротким — це найкращий результат.

Типові помилки: симптом → корінь → виправлення

1) Симптом: багато таймаутів, але CPU не завантажений

Корінь: Скиди пакетів на NIC/ядрі (кільцеві буфери, сокет‑буфери) або зовнішня конгестія.

Виправлення: Перевірте ip -s link і netstat -su; збільшіть буфери, зменшіть накладні витрати на пакет, додайте краєве лімітування, масштабуйтесь горизонтально/anycast.

2) Симптом: раптовий спайк NXDOMAIN‑відповідей

Корінь: Флуд випадкових піддоменів або некоректний клієнт, що генерує нісенітницькі qname.

Виправлення: Підвищіть негативний TTL розумно, застосуйте NXDOMAIN‑ліміти і знайдіть мережі‑джерела з ентропією у qname.

3) Симптом: масивне зростання TCP‑DNS з’єднань

Корінь: Усічення через надмірні UDP‑відповіді (DNSSEC, великі TXT), неправильний EDNS‑розмір, або навмисний перевод у TCP для виснаження.

Виправлення: Обмежте EDNS UDP size, мінімізуйте великі відповіді, забезпечте пропускну здатність TCP та лімітуйте зловмисні qtype.

4) Симптом: «випадкові» відмови клієнтів за мобільними мережами

Корінь: Лімітування по IP карає NAT‑овані популяції або великі резолвери.

Виправлення: Використовуйте вищі ліміти по IP, внесіть у білий список великі резолвери, або перейдіть на ліміти по qname/qtype, що таргетують аб’юз.

5) Симптом: авторитетні сервери стали випадково відкритими резолверами

Корінь: Увімкнено рекурсію або ACL надто широкі; інколи помилка з’являється копіюванням конфігурації рекурсивного сервера.

Виправлення: Вимкніть рекурсію на авторитетних серверах; проведіть аудит управління конфігами; зовні перевірте, що рекурсія відхилюється.

6) Симптом: все ламається після ввімкнення повного логування запитів

Корінь: I/O і CPU‑накладні витрати; насичення лог‑пайплайну; контенція замків у демоні.

Виправлення: Вимкніть логування спочатку. Потім впровадьте сэмплінг і агреговані метрики. Захоплюйте короткі tcpdump‑зразки замість логування апокаліпсису.

7) Симптом: трафік «переміщається» під час атаки і один POP плавиться

Корінь: Anycast‑зміни шляхів, особливості пріоритизації BGP або прицільна атака на один POP.

Виправлення: Контролюйте маршрути: зменшіть пріоритет для гарячого POP, забезпечте симетрію потужності і підтвердіть, що кожен POP має upstream DDoS‑обробку.

8) Симптом: час рекурсії вибухає, хіт‑рейт кешу падає

Корінь: Обхід кешу через випадкові qname; проблеми з доступністю upstream; замалі кеші.

Виправлення: Лімітуйте клієнтів, увімкніть захист від «небажаних запитів», масштабируйте рекурсори горизонтально і забезпечте різноманітність upstream‑зв’язків.

Чеклісти / покроковий план

Фаза 0: до атаки (зробіть це в спокійний вівторок)

  1. Базуйте нормальне. Запишіть типовий QPS, розподіл qtype, частоту NXDOMAIN, p50/p95 затримки, UDP/TCP співвідношення.
  2. Розділіть ролі. Авторитетний та рекурсивний на різних інстансах і бажано в різних підмережах/краях.
  3. Встановіть адекватні TTL. Не тримайте 30‑секундні TTL для записів, що змінюються раз на місяць.
  4. Визначте політику EDNS. Обмежте UDP‑payload і перевірте сумісність з DNSSEC.
  5. Поставте DNS‑свідомий край. dnsdist або еквівалент з протестованим аварійним набором правил, який можна швидко вмикати.
  6. Репетируйте плейбук. Симулюйте NXDOMAIN‑флуди та проби з великими відповідями в staging.

Фаза 1: під час піка (зберігайте доступність передусім)

  1. Підтвердіть, де болить. Прямий dig до авторитетного; порівняйте внутрішнє і зовнішнє.
  2. Знайдіть лімітуючий фактор. Скиди vs CPU vs затримки upstream (використовуйте завдання вище).
  3. Застосуйте утримання на краю. Лімітуйте за джерелом, потім за qtype/qname, потім обмежте розмір відповідей.
  4. Стабілізуйте p95 затримки. «Швидка помилка» часто краще за повільний успіх у DNS, бо повільність провокує повтори.
  5. Тимчасово відключіть дорогі фічі. Вимкніть детальне логування; розгляньте мінімізацію певних відповідей, якщо безпечно.
  6. Масштабуйте, якщо можете чисто. Більше інстансів за anycast/unicast NS, але переконайтеся, що ви не реплікуєте погану конфігурацію.

Фаза 2: після піка (зменшіть ймовірність повторення)

  1. Класифікуйте трафік. Рефлексія? NXDOMAIN? Легітимний сплеск? Поганий клієнт?
  2. Виправте економічні стимули. Збільшіть TTL, зменшіть розміри відповідей, мінімізуйте ампліфікацію, заблокуйте відкриту рекурсію.
  3. Автоматизуйте запобіжники. Попередньо схвалені правила лімітування і безпечні перемикачі; дашборди з qtype‑міксом і NXDOMAIN‑лічильниками.
  4. Напишіть односторінкову довідку інциденту. Що змінили, що бачили і які лічильники це підтвердили.

Питання й відповіді

1) Чи лімітувати DNS за IP адресу?

Так, але розглядайте це як грубий інструмент. Ліміти за IP можуть карати NAT‑овані популяції і великі публічні резолвери. Комбінуйте з контролем по qtype/qname.

2) Який найбезпечніший перший ліміт під час атаки?

Почніть з краєвого шейпінгу, що таргетує очевидні зловживання: надмірний NXDOMAIN на джерело, підозрілі qtype (ANY сплески, TXT‑флуди) та надмірно великі відповіді. Уникайте глобальних капів.

3) Чи хороший TCP‑fallback чи поганий?

І те, і інше. TCP зменшує корисність підробленої рефлексії і уникає фрагментації, але дорожчий на запит і теж може бути атакований. Проектуйте пропускну здатність для TCP, але не переводьте все примусово в нього.

4) Чи роблять короткі TTL DNS‑атаки гіршими?

Вони роблять будь‑який спайк гіршим, атакувальний або ні, бо рекурсори частіше оновлюють записи. Використовуйте короткі TTL лише там, де справді потрібне швидке переключення.

5) Як зрозуміти, чи мене використовують для ампліфікації?

Шукайте багато запитів з підробленими джерелами (складно довести напряму), незвичні qtype (DNSKEY, ANY) і співвідношення байт відповіді до запиту, що виглядає «нелогічно». Зразки пакетів допомагають.

6) Чи можу я покластися на DNS‑провайдера і не паритись?

Ви можете аутсорсити інфраструктуру, але не відповідальність. Вам все одно потрібні адекватні TTL, розумний вміст зони і план інциденту. Провайдери не виправлять зону, яка сама по собі спроектована для ампліфікації.

7) У чому різниця між NXDOMAIN і NODATA, і чому це важливо?

NXDOMAIN означає, що ім’я не існує. NODATA означає, що ім’я існує, але немає запиту‑типу. Атаки використовують обидва, аби обходити кеші; негативний TTL визначає, як часто резолвери перепитують.

8) Чи вимикати ANY повністю?

Для авторитетних серверів варто принаймні мінімізувати відповіді на ANY. Деякі клієнти ще використовують ANY для діагностики. Надавайте мінімальну безпечну відповідь, а не величезну.

9) Чому мій DNS «працює» зсередини VPC, але не з інтернету?

Внутрішній трафік обходить краєве насичення і зовнішнє фільтрування. Зовнішні проблеми часто вказують на PPS‑насичення, скрабінг DDoS, будькаст‑зміни маршруту або проблеми MTU/фрагментації.

10) Які метрики мають бути на дашборді DNS?

QPS, PPS, p50/p95 затримка, співвідношення UDP vs TCP, частота NXDOMAIN, топ qtype, розподіл розмірів відповідей, скиди ядра і NIC, і хіт/місси кешу (для рекурсії).

Висновок: подальші кроки, що реально зменшують простої

Якщо ви хочете, щоб DNS переживав піки без простоїв, припиніть думати в категоріях «заблокуємо нападника». Думайте у категоріях захисту затримки для легітимного трафіку, одночасно роблячи зловживання дорогими й нецікавими.

  1. Реалізуйте DNS‑свідомий край (dnsdist або еквівалент) і попередньо підготуйте аварійні правила для NXDOMAIN‑флуду та зловмисних qtype.
  2. Обмежте EDNS UDP size і перевірте поведінку DNSSEC, щоб не фрагментувати себе в відмови.
  3. Перегляньте TTL‑стратегію: підвищте TTL там, де можна, підніміть негативний TTL до розумного значення і зберігайте «швидке переключення» лише для небагатьох критичних записів.
  4. Інструментуйте скиди й затримки на рівні NIC/ядра і демона. Один лише графік CPU — шлях до легенд про інциденти.
  5. Репетируйте плейбук щоквартально. Час вчитися, які ручки б’ють клієнтів, не під час атаки.

DNS має бути нудним. Зробіть його знову нудним — інженеруйте його як критичну інфраструктуру, бо так воно і є.

← Попередня
Крах Nokia: як король телефонів пропустив поворот
Наступна →
Proxmox pvedaemon.service не працює: чому завдання не запускаються і як це виправити

Залишити коментар