Обычный DNS не проверяет подлинность ответов. Злоумышленник может перехватить ответ резолвера и подсунуть свой IP-адрес — клиент об этом не узнает.
DNSSEC (DNS Security Extensions) решает эту проблему: каждый набор записей подписывается криптографически. Резолвер проверяет подпись перед тем, как вернуть ответ клиенту.
Зона — область ответственности. Каждый домен обслуживается конкретными NS-серверами, которые хранят файл зоны со всеми записями.
. ← корневая зона (13 корневых серверов)
├── org. ← зона .org
│ └── iana.org. ← зона iana.org (серверы ICANN)
└── ru.
└── yandex.ru. ← зона yandex.ru (серверы Яндекса)
DNSSEC использует асимметричную криптографию: два связанных ключа — приватный (секретный) и публичный (открытый). То, что зашифровано приватным, можно проверить публичным.
Процесс подписи:
1. Берём запись:
iana.org. 3600 IN A 192.0.32.8
2. Хэшируем (SHA-256) → получаем «отпечаток»:
iana.org. A 192.0.32.8 → a3f9c2...
3. Шифруем отпечаток приватным ключом ZSK:
a3f9c2... + приватный ZSK → 8b71de... (это RRSIG)
RRSIG публикуется в DNS рядом с самой записью.
Процесс проверки на резолвере:
RRSIG приходит от авторитетного сервера в том же ответе, что и сама запись:
;; ANSWER SECTION:
iana.org. 3600 IN A 192.0.32.8
iana.org. 3600 IN RRSIG A 8 2 3600 ... 8b71de...
RRSIG хранится прямо в файле зоны рядом с каждой подписанной записью. Владелец зоны подписал заранее, положил в зону — сервер раздаёт всем.
Получив ответ, резолвер проверяет подпись:
1. Хэшируем полученную A-запись:
iana.org. A 192.0.32.8 → SHA-256 → a3f9c2...
2. Расшифровываем RRSIG публичным ключом ZSK:
8b71de... + публичный ZSK → a3f9c2...
3. Сравниваем:
a3f9c2... == a3f9c2... ✓ → запись подлинная
Подделать RRSIG без приватного ключа математически невозможно.
Формально можно было бы использовать один ключ. Но тогда при его смене пришлось бы каждый раз обновлять DS-запись в родительской зоне через регистратора — это административная процедура, её неудобно делать часто.
Поэтому роли разделены:
| ZSK (Zone Signing Key) | KSK (Key Signing Key) | |
|---|---|---|
| Что подписывает | Все записи зоны (A, MX, NS…) | Только DNSKEY-запись (то есть сам ZSK) |
| Как часто меняется | Часто (раз в месяц) | Редко (раз в год и реже) |
| Где хранится хэш | Нигде — его проверяет KSK | В DS-записи родительской зоны |
ZSK можно менять часто — регистратор не нужен. KSK меняется редко — DS-запись у регистратора обновляется раз в год.
Якорь доверия — в Unbound жёстко зашит хэш ключа корневой зоны (.). Это отправная точка, которой резолвер доверяет безусловно.
Дальше цепочка строится через DS-записи (Delegation Signer — хэш KSK дочерней зоны, хранится в родительской зоне):
Якорь доверия (зашит в Unbound)
↓ доверяем
Ключ корня (.) → проверяет DS зоны .org
↓ доверяем
Ключ .org → проверяет DS зоны iana.org
↓ доверяем
KSK iana.org → проверяет ZSK iana.org (через RRSIG на DNSKEY)
↓ доверяем
ZSK iana.org → проверяет A, MX, NS... (через RRSIG на каждой записи)
↓ доверяем
192.0.32.8 ← это число точно настоящее
1. Создать два ключа: ZSK и KSK (приватный + публичный для каждого).
Приватные ключи хранятся в секрете у владельца зоны — нигде не публикуются.
2. Публичный ZSK и публичный KSK опубликовать в зоне как DNSKEY-записи.
3. Подписать все записи зоны (A, MX, NS...) приватным ZSK
→ получаем RRSIG для каждой записи.
4. Подписать DNSKEY-записи (содержащие публичные ZSK и KSK) приватным KSK
→ получаем RRSIG для DNSKEY.
Таким образом KSK «ручается» за публичный ZSK.
5. Вычислить хэш публичного KSK → передать регистратору как DS-запись.
Регистратор публикует DS в родительской зоне (.org).
iana.org A)1. Резолвер идёт к корню → получает NS .org + DS iana.org + RRSIG(DS)
2. Проверяет RRSIG(DS) через ключ корня (из якоря) ✓
3. Идёт к серверам iana.org → получает DNSKEY (ZSK+KSK) + RRSIG(DNSKEY)
4. Хэширует KSK → сравнивает с DS из шага 1 ✓ → KSK доверенный
5. Проверяет RRSIG(DNSKEY) через KSK ✓ → ZSK доверенный
6. Запрашивает A-запись + RRSIG(A)
7. Проверяет RRSIG(A) через ZSK ✓ → возвращает 192.0.32.8
Если хотя бы одна проверка провалилась — резолвер возвращает SERVFAIL.
ad в dig;; flags: qr rd ra ad;
ad (Authenticated Data) — резолвер успешно проверил всю цепочку DNSSEC.
domain-insecure нужен для local-zoneПри создании local-zone: "iana.org" static локальные local-data не подписаны. Validator Unbound пытается проверить RRSIG → не находит → SERVFAIL.
Директива domain-insecure: "iana.org" говорит валидатору: не требуй подпись для этой зоны. Именно это позволяет подменить DNSSEC-зону локальными данными.