↓ До тексту
  1. Статті/

PowerDNS: DNSSEC за одну команду

cat /etc/passwd
Автор
cat /etc/passwd
Технічний блог про Linux, DevOps та Open Source технології.
Зміст
Відмовостійкий DNS - частина серії статей.
Частина 6: ця стаття (ти тут)

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

У PowerDNS DNSSEC вмикається буквально однією командою: сервер сам генерує ключ і підписує відповіді онлайн (на льоту, нічого не треба перепідписувати руками). А найприємніше для нашої схеми: ключі живуть у тій самій базі MariaDB, що й зони, - тож вони їдуть реплікацією, і репліка починає віддавати зону підписаною сама.

Що потрібно зробити?
#

Підписати зону на майстрі (secure-zone), подивитись на ключ і підпис (RRSIG), дістати DS-запис для реєстратора - і переконатися, що репліка віддає ту саму зону підписаною, хоча DNSSEC на ній ми не чіпали (ключ приїхав реплікацією). Двопанельний запис: ліворуч ns1 (майстер), праворуч ns2 (репліка).

З чим працюю?
#

Той самий стенд: майстер + репліка з частини 2. Бекенд уже з gmysql-dnssec=yes (ми виставили це ще в частині 1) - тож PowerDNS готовий зберігати ключі в базі (таблиця cryptokeys) і підписувати. Нічого нового ставити не треба.

Далі те саме, що в записі, тільки вже можна копіювати.

Поки без підпису
#

Спитаємо зону з прапором DNSSEC (+dnssec) напряму в pdns (на :5300, повз dnsdist):

1
dig +dnssec @127.0.0.1 -p 5300 example.com SOA +noall +answer

У відповіді лише SOA - жодного RRSIG. Підпису немає, перевіряти нічого.

Вмикаємо DNSSEC
#

Одна команда на майстрі:

1
2
3
4
pdnsutil secure-zone example.com
# Securing zone with default key size
# Adding CSK (257) with algorithm ecdsa256
# Zone example.com secured

PowerDNS згенерував CSK (Combined Signing Key - один ключ і для підпису ключів, і для підпису записів) з алгоритмом ECDSA P-256 (сучасний дефолт: короткі ключі, швидкі підписи). Дивимось на нього:

1
2
pdnsutil show-zone example.com | grep 'ID ='
# ID = 1 (CSK), flags = 257, tag = 56910, algo = 13, bits = 256   Active  Published ( ECDSAP256SHA256 )

Тепер та сама відповідь іде з підписом:

1
2
3
dig +dnssec @127.0.0.1 -p 5300 example.com SOA +noall +answer
# example.com.  3600 IN SOA   ns1.example.com. hostmaster.example.com. ...
# example.com.  3600 IN RRSIG SOA 13 2 3600 20261029000000 ... example.com. e2qXK4h...==

З’явився RRSIG - підпис запису SOA ключем з тегом 56910. PowerDNS підписує відповіді на льоту, тримати окремий «підписаний файл зони» не треба.

DS - єдиний ручний крок
#

Щоб резолвери довіряли нашому ключу, батьківська зона (.com) має вказати на нього - через DS-запис. PowerDNS його порахує:

1
2
3
pdnsutil export-zone-ds example.com
# example.com. IN DS 56910 13 2 f7d31bb291f0c7ecbe3df69842652c9e28dac36fe2e220c49a7397df9fc663c8 ; ( SHA256 digest )
# example.com. IN DS 56910 13 4 e7af2bd91c842c10728735bef379f25a9dda2b36d494ea4661fa23748393e763576e9db7ddc690e424177de77345a152 ; ( SHA-384 digest )

Цей DS вставляємо в реєстратора (у панелі домену - розділ «DNSSEC»). Відтоді ланцюжок довіри замкнений: корінь → .com → наша зона. Це єдина ручна дія - усе решта PowerDNS робить сам.

Головне: репліка підписана сама
#

А тепер найцікавіше для нашої схеми. На репліці ми DNSSEC не вмикали. Але ключі - у базі, а база реплікується:

1
2
3
4
5
6
# на ns2 (репліці)
mysql -e 'SELECT id,flags,active,published FROM cryptokeys' pdns
# +----+-------+--------+-----------+
# | id | flags | active | published |
# |  1 |   257 |      1 |         1 |
# +----+-------+--------+-----------+

Ключ на місці - приїхав реплікацією MariaDB. І репліка вже віддає зону підписаною, тим самим ключем (tag 56910):

1
2
3
# на ns2 (репліці)
dig +dnssec @127.0.0.1 -p 5300 example.com SOA +noall +answer
# example.com.  3600 IN RRSIG SOA 13 2 3600 ... 56910 example.com. XhZCXFc...==

Підписали лише на майстрі - DNSSEC поїхав на репліку сам. Жодного копіювання ключів, жодного окремого налаштування на другому сервері.

NSEC vs NSEC3
#

За замовчуванням PowerDNS використовує NSEC - він простіший, але дозволяє «пройтись» зоною й вивудити всі імена (zone walking). Якщо це небажано, вмикаємо NSEC3 (імена захешовані):

1
pdnsutil set-nsec3 example.com '1 0 0 -'

Параметри 1 0 0 - - це сучасна рекомендація (SHA-1, 0 ітерацій, без солі): ітерації й сіль нині вважають зайвими.

Граблі
#

  • Кеш dnsdist віддає стару (непідписану) відповідь. Якщо питати через dnsdist (:53), packet cache ще якийсь час (до свого TTL) віддаватиме відповідь, закешовану до підпису. Тому перевіряємо напряму в pdns (:5300), а кеш dnsdist або чистимо (clearPacketCache() у консолі), або чекаємо TTL.
  • DS - єдиний ручний крок, і його легко забути. Без DS у реєстратора зона технічно підписана, але ланцюжок довіри розірваний - валідаційні резолвери це просто проігнорують (зона виглядає як непідписана). DNSSEC «вмикається» лише коли DS опубліковано в батька.
  • Міняти ключі (rollover) теж колись треба. CSK зручний (один ключ), але при зміні доведеться оновлювати DS у реєстратора. Для рідкісної зміни це норм; хто хоче міняти ZSK частіше, не чіпаючи DS, розділяє на KSK+ZSK (pdnsutil add-zone-key).
  • Серіал SOA має рости при змінах. DNSSEC цього не любить: стара відповідь зі старим підписом і новий запис конфліктують. У нас серіал підбиває API автоматично (SOA-EDIT-API DEFAULT) - якщо правите зону повз API, не забувайте pdnsutil increase-serial.

Що далі
#

DNSSEC закрив автентичність відповідей. Серія вже охоплює дані (реплікація), вхід (dnsdist + два NS), захист від флуду (UDP і TCP) і тепер підпис. Наступний напрошується візуальний матеріал - веб-панелі поверх API: порівнюємо PowerDNS-Admin і Poweradmin, щоб керувати зонами, записами й DNSSEC мишкою, а не в терміналі.

Підсумок
#

DNSSEC у PowerDNS - це справді одна команда: secure-zone генерує ключ, сервер підписує онлайн, а export-zone-ds дає DS для реєстратора. Для нашої master-slave схеми бонус безкоштовний: ключі лежать у базі, тож репліка підхоплює підпис реплікацією й віддає зону підписаною сама. Лишається єдина ручна дія - вставити DS у реєстратора, і ланцюжок довіри від кореня до вашої зони замкнений.

Відмовостійкий DNS - частина серії статей.
Частина 6: ця стаття (ти тут)

Related

dnsdist: захист від флуду TCP-зʼєднань

·5 хвилин
У частині 4 ми різали UDP-флуд запитами. Але атака буває по TCP-зʼєднаннях: мало запитів, багато конектів - і TCP-потоки сервера забиті. Ставимо в dnsdist ліміти зʼєднань: скільки одночасних з одного IP, скільки запитів на конект, скільки конект живе. Наживо відкриваємо 60 зʼєднань з однієї машини й бачимо, як їх ріже до 5, а чесний клієнт не помічає.

dnsdist проти флуду: rate-limit і динамічні блоки

Резолвери заливають authoritative-сервер запитами, і pdns захлинається. Ставимо захист у dnsdist: ліміт на IP з форсуванням TCP проти спуфленого UDP і динамічні блоки, що тимчасово банять абʼюзера. Заливаємо сервер наживо з сусідньої машини - потік падає з 800 до ~100 запитів/с, а чесний клієнт не помічає. Частина серії про відмовостійкий authoritative DNS.

PowerDNS: реплікація MariaDB між двома DNS-серверами

·6 хвилин
Другий DNS-сервер на репліці MariaDB: master-slave з GTID по окремій приватній мережі, pdns на репліці read-only. Зміна через API на майстрі миттєво на репліці. Живий двопанельний запис. Друга частина серії про відмовостійкий authoritative DNS.