Отказоустойчивость авторитативного DNS чаще всего начинается не с «магии» балансировщиков, а с базового требования DNS-платформы: домен должен иметь минимум два независимых NS-сервера. Практичный сценарий для небольшой инфраструктуры – две виртуальные машины (VM) с классической схемой master-slave (primary-secondary), где мастер хранит исходные зоны и подписывает их DNSSEC, а слейв получает данные по AXFR/IXFR и обслуживает запросы наравне с мастером.

Ниже приводится прикладная конфигурация для двух VM с BIND9: безопасные трансферы зон через TSIG, автоматическое управление DNSSEC-ключами и подписями, автоперезагрузка зон при изменении файлов и контроль рассинхронизации между узлами с возможностью автоматического «подтягивания» отставших зон.
Что именно считается отказоустойчивостью в DNS
В DNS нет «мгновенного» failover в стиле VRRP: резолверы (кеширующие DNS-серверы провайдеров и публичные резолверы) выбирают один из NS из делегации и при проблемах переключаются на другой. Переключение может занимать секунды или десятки секунд из‑за повторных попыток, а кеширование записей влияет на скорость распространения изменений. Поэтому устойчивость здесь – это:
- два авторитативных узла, доступных по UDP/53 и TCP/53
- согласованные зоны на обоих узлах (включая DNSSEC-данные)
- контроль состояния репликации и своевременное устранение рассинхронизации
Целевая схема на двух VM
Логическая модель выглядит так:
ns1.example.com – master (primary): источник зон, инициирует NOTIFY, при включенном DNSSEC выполняет автоматическую подпись.
ns2.example.com – slave (secondary): принимает IXFR/AXFR, обслуживает запросы как полноценный NS.
Для доменов вида example.com, где NS лежат внутри самого домена (ns1.example.com, ns2.example.com), у регистратора потребуются «glue»-записи (A/AAAA для NS). Без glue резолвер не сможет найти адреса NS, пока зона недоступна – это типичный источник «самозависимых» отказов.
Выбор и подготовка виртуальных серверов
Для авторитативного DNS обычно подходит небольшой VPS/VDS: нагрузка в основном сетевого характера, а CPU становится критичным при большом количестве зон и активной DNSSEC-подписи. Надежность чаще упирается не в мощность, а в независимость площадок и корректную сетевую фильтрацию.
Практически полезные критерии для двух VM:
- разные площадки или хотя бы разные хосты/стойки у провайдера (в пределах одного датацентра общий риск остается выше)
- публичные статические IPv4, желательно также IPv6
- возможность открыть TCP/53 (критично для трансфера зон) и UDP/53 (обычные ответы)
- корректная синхронизация времени (DNSSEC чувствителен к времени жизни подписей)
В роли одной из площадок может выступать VPS.house (Москва) – как иллюстрация типичного сервиса аренды VDS с публичными адресами. Принципиально важнее другое: два NS желательно располагать в разных сетевых доменах отказа.
Обязательная подготовка на обеих VM:
- включить NTP/chrony (подходит systemd-timesyncd или chrony)
- ограничить доступ по SSH и обновлять пакеты безопасности
- на фаерволе разрешить UDP/53 и TCP/53 извне; входящие подключения на TCP/53 иногда забывают, из‑за чего AXFR/IXFR «молча» не работают
Установка BIND9 и режим «только авторитативный»
Пример для Debian/Ubuntu:
Установка:
apt update
apt install bind9 bind9utils dnsutils
Ключевой момент – запрет рекурсии, чтобы сервер не превращался в «open resolver» (это риск злоупотреблений и DDoS-отражения).
Пример /etc/bind/named.conf.options для авторитативного режима (адаптируется под дистрибутив):
named.conf.options:
options {
directory «/var/cache/bind»;
listen-on { any; };
listen-on-v6 { any; };
recursion no;
allow-recursion { none; };
allow-query-cache { none; };
dnssec-validation no; // сервер авторитативный, не валидатор
version «not disclosed»;
minimal-responses yes;
};
Параметр dnssec-validation уместно отключать именно на авторитативных узлах: они публикуют данные, а не валидируют ответы других серверов. Валидация – задача рекурсивных резолверов.
TSIG для AXFR/IXFR и NOTIFY: защищаем репликацию
Зоны между master и slave переносятся по AXFR (полный трансфер) или IXFR (инкрементальный). В открытом виде трансферы раскрывают структуру зоны и часто используются злоумышленниками для разведки. Поэтому в реальных внедрениях трансферы ограничиваются по IP и подписываются TSIG-ключом.
Генерация TSIG-ключа
TSIG создается на master и копируется на slave (секрет должен совпадать):
tsig-keygen -a hmac-sha256 axfr-ns2 > /etc/bind/keys/axfr-ns2.key
chmod 640 /etc/bind/keys/axfr-ns2.key
chown root:bind /etc/bind/keys/axfr-ns2.key
Файл /etc/bind/keys/axfr-ns2.key затем переносится на slave по защищенному каналу (например, scp) с теми же правами доступа.
Дополнительно указывается «привязка» ключа к адресу противоположной стороны через server-блок – это снижает риск ошибочного применения ключа к другим серверам.
Настройка master (primary): зоны, NOTIFY и автоматический DNSSEC
Ниже используется современная терминология BIND (type primary/secondary), но на многих версиях остаются совместимые master/slave.
Подключение TSIG и привязка к slave
В /etc/bind/named.conf.local (или отдельном include) добавляется:
named.conf.local (фрагмент):
include «/etc/bind/keys/axfr-ns2.key»;
server 198.51.100.20 {
keys { «axfr-ns2»; };
};
Где 198.51.100.20 – адрес slave. В примерах используются тестовые подсети RFC 5737 (203.0.113.0/24, 198.51.100.0/24).
Определение зоны на master
Пример для зоны example.com:
zone «example.com» {
type primary;
file «/etc/bind/zones/db.example.com»;
notify yes;
also-notify { 198.51.100.20; };
allow-transfer { key «axfr-ns2»; };
// DNSSEC: автоматическое управление ключами и подписями
inline-signing yes;
dnssec-policy «default»;
// для подписанных зон серийный номер управляется сервером
serial-update-method unixtime;
};
inline-signing и dnssec-policy включают полностью автоматизированный сценарий DNSSEC: генерация ключей, публикация DNSKEY, выпуск RRSIG и регулярное пере-подписание. Для мастер-слейв схемы это удобно тем, что слейв получает уже подписанную зону по трансферу и не должен иметь доступ к ключам.
Пример файла зоны
Каталог зон на master удобно вынести отдельно:
mkdir -p /etc/bind/zones
Пример /etc/bind/zones/db.example.com:
$TTL 300
@ IN SOA ns1.example.com. hostmaster.example.com. (
2026011501 ; serial (для человека; при inline-signing внешний serial может меняться автоматически)
3600 ; refresh
900 ; retry
1209600 ; expire
300 ; negative cache
)
IN NS ns1.example.com.
IN NS ns2.example.com.
ns1 IN A 203.0.113.10
ns2 IN A 198.51.100.20
@ IN A 203.0.113.50
www IN CNAME @
Таймеры SOA подбираются под частоту обновлений и требования к скорости восстановления. Часто встречаются refresh порядка часа и retry 10-15 минут, но это именно эксплуатационный компромисс: слишком маленькие значения увеличивают фоновый трафик и нагрузку.
Проверка конфигурации и запуск
named-checkconf
named-checkzone example.com /etc/bind/zones/db.example.com
systemctl enable —now bind9
В логах после первого запуска при включенном DNSSEC обычно появляются сообщения о генерации ключей и начальной подписи.
Настройка slave (secondary): прием трансферов и хранение зон
На slave устанавливается BIND9 аналогично master. Далее подключается тот же TSIG-ключ и объявляется зона как secondary.
TSIG и привязка к master
named.conf.local (slave, фрагмент):
include «/etc/bind/keys/axfr-ns2.key»;
server 203.0.113.10 {
keys { «axfr-ns2»; };
};
Определение зоны на slave
zone «example.com» {
type secondary;
file «/var/cache/bind/slaves/db.example.com»;
masters { 203.0.113.10 key «axfr-ns2»; };
allow-notify { 203.0.113.10; };
};
Каталог /var/cache/bind/slaves должен быть доступен пользователю, от которого работает named (в Debian/Ubuntu – bind).
Первичная синхронизация
После перезагрузки конфигурации slave запросит зону у master:
systemctl restart bind9
journalctl -u bind9 -n 100 —no-pager
Проверка SOA на обоих узлах:
dig @203.0.113.10 example.com SOA +short
dig @198.51.100.20 example.com SOA +short
Для DNSSEC дополнительно проверяется наличие DNSKEY и RRSIG:
dig @203.0.113.10 example.com DNSKEY +dnssec +multiline
dig @198.51.100.20 example.com DNSKEY +dnssec +multiline
DNSSEC в схеме master-slave: важные детали эксплуатации
DNSSEC добавляет криптографическую проверяемость ответа, но вводит новые классы проблем: подписи имеют сроки действия, а делегация требует публикации DS у регистратора. В схеме из двух VM удобен подход «подпись на master, доставка подписанной зоны на slave» – ключи остаются на одной ноде, а вторичная только раздает уже готовые данные.
Публикация DS у регистратора
После включения dnssec-policy BIND создаст ключи (KSK/ZSK) и начнет публиковать DNSKEY и подписи. Для построения цепочки доверия требуется DS в родительской зоне (обычно через панель регистратора).
DS можно получить из состояния зоны или из ключевых файлов. На современных версиях BIND информативен вывод:
rndc dnssec -status example.com
Если панель регистратора поддерживает автоматизацию по RFC 8078, иногда используется публикация CDS/CDNSKEY (в зависимости от политики и поддержки регистратором). Но универсальным вариантом остается ручное добавление DS, особенно в средах с консервативными правилами изменения делегаций.
Синхронизация времени
При DNSSEC любые отклонения времени на VM быстро превращаются в «все сломалось»: подписи могут оказаться «из будущего» или «просроченными». Поэтому NTP/chrony – не опция, а обязательное условие.
Риск «долгой» недоступности master
Если master недоступен длительное время, slave продолжит отвечать из последней полученной копии зоны. Однако при очень долгом простое возникает теоретический риск истечения RRSIG, если подписи не обновляются. На практике это решается сочетанием:
- адекватной политики подписи (с запасом по времени жизни подписей)
- мониторинга срока действия подписей и состояния DNSSEC валидации с внешней точки
- обеспечения доступности master как минимум на уровне «иногда поднимается для обновления подписей»
Автоматическая перезагрузка зон на master при изменении файлов
BIND не обязан автоматически перечитывать файл зоны сразу после изменения на диске. В результате частая операционная ошибка выглядит так: файл поправлен, но сервер продолжает отдавать старую версию до ручного rndc reload. Для устранения человеческого фактора удобно применять связку systemd.path + сервис проверки/перезагрузки.
Сервис проверки и reload
Скрипт перезагрузки (пример /usr/local/sbin/bind-zones-reload.sh):
#!/bin/sh
set -eu
ZONEDIR=«/etc/bind/zones»
# 1. проверка конфигурации
named-checkconf >/dev/null
# 2. проверка всех зон в каталоге (подход удобен при небольшом количестве зон)
for f in «$ZONEDIR»/db.*; do
zone=$(basename «$f» | sed ‘s/^db\.//’)
named-checkzone «$zone» «$f» >/dev/null
done
# 3. reload + notify
rndc reload
rndc notify
logger -t bind-zones «zones validated and reloaded»
Важно: при включенном inline-signing внешний SOA serial обслуживаемой зоны может изменяться автоматически (серийный номер для «подписанной» версии живет своей жизнью). Поэтому контроль «увеличился ли serial в файле» не всегда отражает реальное состояние, а мониторинг синхронизации корректнее строить по ответам DNS и состоянию secondary.
systemd unit и systemd path
Unit-файл /etc/systemd/system/bind-zones-reload.service:
[Unit]
Description=Validate and reload BIND zones
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/bind-zones-reload.sh
Path unit /etc/systemd/system/bind-zones-reload.path:
[Unit]
Description=Watch BIND zone directory for changes
[Path]
PathModified=/etc/bind/zones
[Install]
WantedBy=multi-user.target
Активация:
chmod +x /usr/local/sbin/bind-zones-reload.sh
systemctl daemon-reload
systemctl enable —now bind-zones-reload.path
Такой механизм обеспечивает «самопубликацию» изменений: файл зоны изменен – конфигурация проверена – зона перезагружена – slave получает NOTIFY и запрашивает IXFR/AXFR.
Контроль рассинхронизации: SOA, состояние secondary и автокоррекция
Рассинхронизация в master-slave DNS обычно проявляется в трех видах:
- slave не получает NOTIFY (фильтрация, ACL, проблемы с TSIG)
- slave получает NOTIFY, но трансфер не проходит (закрыт TCP/53, неверный ключ, разрыв маршрута)
- slave долго «висит» на старой версии, пока не сработает refresh или пока зона не истечет по expire
Быстрая внешняя проверка: сравнение SOA serial
Минимально достаточный контроль – периодически сравнивать SOA serial, который отдают оба NS из интернета. Этот тест улавливает «одна нода отстала», не требуя доступа по SSH.
Идея проверки (псевдокод для cron/CI/мониторинга):
NS1=203.0.113.10
NS2=198.51.100.20
ZONES=«example.com example.net»
for z in $ZONES; do
s1=$(dig +short @$NS1 $z SOA | awk ‘{print $3}’)
s2=$(dig +short @$NS2 $z SOA | awk ‘{print $3}’)
[ «$s1» = «$s2» ] || echo «DESYNC $z: $s1 vs $s2»
done
Если используется DNSSEC inline-signing, serial может увеличиваться не только при изменении записей, но и при пере-подписи. Это нормальное поведение: цель serial – отражать актуальную версию обслуживаемой зоны, а не только ручные правки.
Диагностика на slave: rndc zonestatus
На secondary для диагностики полезен rndc zonestatus – он показывает тайминги refresh/retry, текущий serial и время последней загрузки:
rndc zonestatus example.com
По этому выводу легко обнаруживаются ситуации, когда зона давно не обновлялась или застряла на retry.
Автокоррекция на slave: принудительный retransfer при отставании
Если требуется не только обнаруживать, но и автоматически устранять отставание, на slave запускается периодическая проверка. Логика: сравнить serial на master и на локальном slave, и при отставании инициировать rndc retransfer.
Пример простого скрипта (запуск раз в 5-10 минут через cron/systemd timer):
#!/bin/sh
set -eu
MASTER=203.0.113.10
ZONES=«example.com»
for z in $ZONES; do
ms=$(dig +short @$MASTER $z SOA | awk ‘{print $3}’)
ls=$(dig +short @127.0.0.1 $z SOA | awk ‘{print $3}’)
if [ -n «$ms» ] && [ -n «$ls» ] && [ «$ms» -gt «$ls» ]; then
logger -t bind-sync «zone $z is behind ($ls < $ms), forcing retransfer»
rndc retransfer $z || logger -t bind-sync «retransfer failed for $z»
fi
done
Такая автокоррекция не заменяет мониторинг причин, но сокращает окно «зона отстает», если проблема временная (кратковременный сетевой сбой, короткая недоступность master).
Проверки, без которых схема часто ломается
- TCP/53 открыт между master и slave. Зона может успешно отвечать по UDP/53, но трансферы все равно не пройдут
- ACL и TSIG согласованы. Несовпадение секретов, алгоритма или ошибочная привязка ключа к IP приводит к отказу трансфера
- Нет рекурсии. Проверка: dig @ns1 example.org A +recurse должна возвращать отказ/без рекурсии, а не выполнять резолвинг
- В делегации прописаны оба NS и корректные glue. Иначе технически исправные VM не помогут
- DNSSEC проверен «снаружи». Удобны проверки через dig +trace +dnssec, а также валидаторы уровня DNSViz/Zonemaster
Границы «двух VM» и практичные улучшения
Две VM заметно улучшают доступность DNS по сравнению с одним сервером, но не дают абсолютной устойчивости. Общие точки отказа остаются: регистратор, ошибки делегации, массовые блокировки, проблемы маршрутизации у конкретного оператора. Поэтому распространенная практическая рекомендация – разводить NS по разным провайдерам или регионам, когда это возможно.
Если требуется быстро развернуть второй узел в другом сегменте сети для повышения независимости, иногда удобно иметь возможность оперативно поднять виртуальный сервер в Москве или в другой географии у альтернативного провайдера. При этом ключевым остается не место размещения как таковое, а различие сетевых и инфраструктурных доменов отказа.
Для сценариев с десятками и сотнями зон дополнительно рассматриваются:
- каталожные зоны (Catalog Zones) для автоматического появления новых зон на secondary без ручного дублирования конфигов (при поддержке используемой версии BIND)
- вынос управления зонами в Git/CI с автоматической валидацией и доставкой на master
- интеграция проверок рассинхронизации в Zabbix/Prometheus с алертами, а не только с «самолечением»
Короткий эксплуатационный чек-лист
- UDP/53 и TCP/53 доступны извне на обоих узлах; TCP/53 доступен между узлами
- Рекурсия отключена, кеш не обслуживается
- TSIG включен, allow-transfer ограничен ключом и адресом slave
- NOTIFY включен (notify/also-notify), на slave разрешен allow-notify от master
- DNSSEC включен на master, DS опубликован у регистратора, валидируется внешними резолверами
- Автоперезагрузка зон настроена (systemd.path или аналог), изменения не «забываются»
- Мониторинг сравнивает SOA serial и/или анализирует zonestatus; при отставании есть понятный сценарий восстановления (retransfer)
При соблюдении этих условий связка master-slave на двух виртуальных серверах дает предсказуемую и управляемую отказоустойчивость DNS без внешних зависимостей, с DNSSEC и контролем целостности репликации – ровно в той мере, которая обычно требуется для доменов с собственной инфраструктурой.