Zone transfer — это штатный механизм, с помощью которого authoritative DNS-серверы синхронизируют содержимое зоны. Обычно один сервер считается primary: на нём администратор правит zone file и увеличивает SOA serial. Один или несколько secondary серверов забирают копию зоны по AXFR или IXFR и начинают отвечать за домен как полноценные авторитативные NS.
Связка BIND9 и NSD встречается часто: BIND9 удобен как универсальный DNS-сервер с привычной конфигурацией, а NSD — лёгкий и строгий authoritative-only сервер без рекурсивного резолвера. Но у zone transfer есть важный нюанс: открытый AXFR может отдать всю зону любому, кто спросит. Для публичной зоны это не всегда катастрофа, но почти всегда лишняя утечка структуры: поддомены, технические имена, почтовые узлы, staging-окружения и старые записи.
В этой инструкции настроим безопасный DNS zone transfer между BIND9 и NSD с TSIG, проверим AXFR через dig, разберём отличие AXFR от IXFR и типовые ошибки вроде REFUSED, NOTAUTH, bad key и ситуации «зона не обновляется, хотя serial вырос».
Примеры используют документационные IP-адреса и домен
example.org. Замените их на свои значения: primary NS, secondary NS, имя зоны и секрет TSIG.
Что такое AXFR, IXFR и TSIG в одной схеме
В DNS zone transfer участвуют минимум два authoritative-сервера. Primary хранит исходную версию зоны, secondary получает копию и периодически проверяет SOA serial. Если serial на primary больше, secondary запрашивает обновление.
AXFR— полный трансфер зоны. Secondary забирает всю зону целиком. Это проще для диагностики и совместимости, но для больших зон тяжелее по трафику и CPU.IXFR— инкрементальный трансфер. Secondary получает только изменения между старым и новым serial, если primary хранит журнал изменений.NOTIFY— уведомление от primary к secondary: «зона изменилась, проверь SOA». Без NOTIFY secondary всё равно обновится, но только по таймеру refresh из SOA.TSIG— подпись DNS-сообщений общим секретом. Она не шифрует зону, но подтверждает, что запрос пришёл от стороны, знающей ключ, и что пакет не был изменён.
Важно понимать: TSIG — это не TLS. Содержимое AXFR передаётся в открытом виде по TCP/53. Если нужно защитить не только доступ, но и конфиденциальность канала между площадками, обычно добавляют частную сеть, WireGuard/IPsec или другой защищённый транспорт. Для классического контроля доступа к zone transfer TSIG остаётся стандартным и понятным решением.
Исходная топология для примеров
Возьмём такую схему:
ns1.example.org— primary DNS на BIND9, IP192.0.2.10;ns2.example.org— secondary DNS на NSD, IP198.51.100.20;- зона —
example.org; - TSIG key name —
axfr-example-key; - алгоритм —
hmac-sha256.
В продакшене primary и secondary лучше размещать на разных узлах, а ещё лучше — в разных сетях или дата-центрах. Для таких задач обычно удобны отдельные VDS под DNS-инфраструктуру: вы контролируете ОС, firewall, systemd-сервисы и сетевые ACL. Если оба NS стоят на одном сервере, отказ хоста уронит всю авторитативную DNS-инфраструктуру домена, даже если в зоне прописано несколько NS-записей.
Ещё один практический момент: BIND9 и NSD слушают порт 53. Не запускайте оба демона на одном и том же IP:53 без отдельного планирования адресов, контейнеров или jail. В примерах ниже предполагается, что BIND9 и NSD находятся на разных серверах.

Установка пакетов: BIND9 и NSD
Устанавливайте только тот сервер, который нужен конкретному узлу. На primary из нашего примера нужен BIND9, на secondary — NSD и утилиты для диагностики.
Debian/Ubuntu
apt update
apt install -y bind9 bind9-utils dnsutils
apt install -y nsd dnsutils
RHEL-based: AlmaLinux, Rocky Linux, CentOS Stream, Oracle Linux
dnf install -y bind bind-utils
dnf install -y nsd bind-utils
Fedora
dnf install -y bind bind-utils
dnf install -y nsd bind-utils
FreeBSD
pkg install bind918 nsd
На Linux сервис BIND обычно называется по-разному: в Debian/Ubuntu — bind9, в RHEL-based и Fedora — named. NSD почти везде называется nsd.
Генерируем TSIG-ключ
TSIG-ключ нужно создать один раз и безопасно положить на оба сервера. Проще всего сгенерировать его утилитой tsig-keygen на админской машине или на primary:
tsig-keygen -a hmac-sha256 axfr-example-key
Вывод будет похож на такой:
key "axfr-example-key" {
algorithm hmac-sha256;
secret "REPLACE_WITH_BASE64_SECRET==";
};
Секрет в примере заменён заглушкой. В своей конфигурации используйте реальное значение из вывода команды. Не коммитьте его в публичный Git, не отправляйте в тикеты целиком и не оставляйте в shell history, если передаёте через командную строку.
Для BIND9 этот блок почти готов к включению в конфиг. Для NSD синтаксис другой, но имя ключа, алгоритм и secret должны совпадать байт-в-байт.
Настройка BIND9 как primary DNS
Начнём с primary-сервера 192.0.2.10. Удобно хранить TSIG-ключ отдельно от основного файла зон: например, в /etc/bind/keys/axfr-example-key.conf на Debian/Ubuntu или в /etc/named/keys/axfr-example-key.conf на RHEL-based системах. Путь не принципиален, главное — права доступа и понятная структура.
Файл TSIG-ключа для BIND9
key "axfr-example-key" {
algorithm hmac-sha256;
secret "REPLACE_WITH_BASE64_SECRET==";
};
Права стоит сделать такими, чтобы файл мог читать пользователь, под которым работает named, и не могли читать все остальные пользователи системы. На Debian/Ubuntu это часто группа bind, на RHEL-based — пользователь или группа named. Проверяйте локальную раскладку через ps и права на соседних файлах конфигурации.
chown root:bind /etc/bind/keys/axfr-example-key.conf
chmod 640 /etc/bind/keys/axfr-example-key.conf
chown root:named /etc/named/keys/axfr-example-key.conf
chmod 640 /etc/named/keys/axfr-example-key.conf
Не выполняйте команды для обеих семейств ОС подряд: выберите путь и группу, которые реально используются на вашем сервере.
Описание зоны на BIND9
Включите файл ключа и опишите primary-зону. На Debian/Ubuntu это часто делают в /etc/bind/named.conf.local, на RHEL-based — в /etc/named.conf или отдельном include-файле.
include "/etc/bind/keys/axfr-example-key.conf";
zone "example.org" {
type primary;
file "/etc/bind/zones/db.example.org";
allow-transfer { key "axfr-example-key"; };
also-notify { 198.51.100.20 key "axfr-example-key"; };
notify yes;
};
Если у вас старый BIND9, вместо type primary может использоваться исторический синоним type master. В новых конфигурациях лучше писать primary, но оба варианта всё ещё встречаются.
Параметр allow-transfer отвечает за то, кто может забирать зону. В примере разрешён transfer запросам, подписанным TSIG-ключом axfr-example-key. Параметр also-notify говорит BIND9 отправлять NOTIFY на secondary 198.51.100.20 и подписывать уведомление тем же ключом.
Не рассчитывайте только на «секретность» IP-адреса. Для DNS transfer лучше использовать два слоя: TSIG на уровне DNS и firewall/ACL на уровне сети.
Пример минимальной зоны
Файл зоны может выглядеть так. Обратите внимание на SOA serial: именно по нему secondary понимает, что зона изменилась.
$TTL 300
@ IN SOA ns1.example.org. hostmaster.example.org. (
2026011501
300
120
1209600
300
)
@ IN NS ns1.example.org.
@ IN NS ns2.example.org.
ns1 IN A 192.0.2.10
ns2 IN A 198.51.100.20
@ IN A 203.0.113.50
www IN CNAME @
Для небольших зон удобно использовать serial формата YYYYMMDDNN, например 2026011501. При каждом изменении зоны serial нужно увеличивать. Если забыть это сделать, файл на primary будет новым, но secondary не увидит повода обновляться.
Проверка и reload BIND9
Перед перезагрузкой сервиса проверьте синтаксис:
named-checkconf
named-checkzone example.org /etc/bind/zones/db.example.org
Reload зависит от семейства ОС:
systemctl reload bind9
systemctl reload named
service named reload
Не выполняйте все три команды подряд на одном сервере. Для Debian/Ubuntu обычно подходит первая, для RHEL-based и Fedora — вторая, для FreeBSD — третья.
Настройка NSD как secondary DNS
Теперь перейдём к secondary-серверу 198.51.100.20. NSD — authoritative-only сервер, поэтому в нём нет рекурсии для клиентов. Это хорошо для роли публичного NS: меньше лишней поверхности атаки и проще предсказуемость.
Основной файл обычно находится в /etc/nsd/nsd.conf. В некоторых дистрибутивах конфигурация разбита на include-файлы, но синтаксис блоков остаётся тем же.
TSIG-ключ в NSD
key:
name: "axfr-example-key"
algorithm: hmac-sha256
secret: "REPLACE_WITH_BASE64_SECRET=="
Имя, алгоритм и секрет должны полностью совпадать с тем, что настроено в BIND9. Если поменяли хотя бы один символ в secret, NSD получит отказ или BIND9 запишет в лог ошибку проверки TSIG.
Secondary-зона в NSD
zone:
name: "example.org"
zonefile: "secondary/example.org.zone"
allow-notify: 192.0.2.10 axfr-example-key
request-xfr: AXFR 192.0.2.10 axfr-example-key
Директива allow-notify разрешает принимать NOTIFY от primary 192.0.2.10, подписанный ключом axfr-example-key. Директива request-xfr описывает, откуда NSD должен забирать зону и каким TSIG-ключом подписывать запрос.
В примере явно указан AXFR. Для многих небольших зон это нормально: конфигурация проще, поведение предсказуемее. Если у вас большая зона и настроена поддержка журналов изменений, можно рассматривать IXFR, но начинать диагностику всё равно удобнее с полного AXFR.
Проверка и reload NSD
nsd-checkconf /etc/nsd/nsd.conf
systemctl reload nsd
service nsd reload
Как и с BIND9, выбирайте команду reload под свою ОС. Если NSD ещё не запущен, используйте systemctl enable --now nsd на Linux или настройте автозапуск на FreeBSD:
sysrc nsd_enable=YES
service nsd start
Firewall: не забываем про TCP/53
Обычные DNS-запросы часто ассоциируются с UDP/53, но zone transfer выполняется по TCP/53. Если UDP открыт, а TCP закрыт, обычные проверки A/AAAA/MX могут проходить, а AXFR будет зависать или завершаться ошибкой соединения.
На primary нужно разрешить входящий TCP/53 от secondary. На secondary нужно разрешить исходящий TCP/53 к primary, если у вас строгий egress firewall. Также оставьте UDP/53 для обычного обслуживания DNS-запросов и NOTIFY.
Пример логики для nftables, если у вас уже есть таблица inet filter и цепочка input:
nft add rule inet filter input ip saddr 198.51.100.20 tcp dport 53 accept
nft add rule inet filter input ip saddr 198.51.100.20 udp dport 53 accept
Это не универсальный firewall-рецепт, а шаблон. В реальной конфигурации учитывайте порядок правил, default policy, IPv6, cloud firewall у провайдера и то, где именно находится primary.
Проверяем AXFR через dig
Сначала убедимся, что открытый AXFR без TSIG не проходит. С любой машины, где установлен dig, выполните:
dig @192.0.2.10 example.org AXFR
Ожидаемый результат — отказ, например Transfer failed, REFUSED или отсутствие успешной выдачи всех записей зоны. Формулировка зависит от версии сервера и клиента.
Теперь проверим AXFR с TSIG. Подставьте реальный secret. Будьте осторожны: такая команда может попасть в shell history.
dig @192.0.2.10 example.org AXFR -y hmac-sha256:axfr-example-key:REPLACE_WITH_BASE64_SECRET==
Если всё настроено правильно, dig выведет полное содержимое зоны, включая SOA в начале и конце ответа. Это нормальный признак успешного AXFR.
После этого проверьте, что secondary действительно отвечает за зону:
dig @198.51.100.20 example.org SOA
dig @198.51.100.20 www.example.org A
Serial в SOA на secondary должен совпадать с serial на primary. Если primary уже обновлён, а secondary показывает старое значение, смотрите логи BIND9 и NSD, а также таймеры SOA.

Как обновляется зона: serial, refresh и NOTIFY
При изменении зоны на primary администратор обновляет zone file и увеличивает SOA serial. Затем BIND9 перечитывает зону. Если включён notify yes, он отправляет NOTIFY на secondary. NSD принимает уведомление, проверяет SOA на primary и, если serial больше, запрашивает AXFR или IXFR.
Если NOTIFY не дошёл, secondary всё равно периодически проверяет primary по значению refresh из SOA. В нашем примере refresh равен 300 секундам. Это не значит, что все резолверы мира увидят изменения через 300 секунд: на клиентское кеширование влияют TTL записей и кеши рекурсивных резолверов. Refresh управляет только взаимодействием primary и secondary.
Для ручной проверки на NSD можно инициировать transfer зоны:
nsd-control transfer example.org
nsd-control zonestatus example.org
Если nsd-control не настроен, сначала проверьте, включён ли control interface в вашей конфигурации NSD. На некоторых установках он отключён по умолчанию или требует генерации control-сертификатов.
Типовые ошибки и диагностика
REFUSED при AXFR
REFUSED обычно означает, что primary получил запрос, но политика allow-transfer его не пропустила. Проверьте имя TSIG-ключа, алгоритм, secret и то, что запрос действительно подписан. Также убедитесь, что вы обращаетесь к authoritative primary, а не к рекурсивному resolver или другому NS.
journalctl -u bind9 -n 100
journalctl -u named -n 100
journalctl -u nsd -n 100
На Debian/Ubuntu для BIND смотрите bind9, на RHEL-based и Fedora — named. В логах часто прямо видно: неизвестный ключ, неверная подпись, отказ transfer или попытка с неожиданного адреса.
NOTAUTH или zone not authoritative
Ошибка NOTAUTH часто появляется, если сервер, к которому вы обращаетесь, не считает себя авторитативным для этой зоны. Причины банальны: зона не подключена, конфиг не перечитан, файл зоны не прошёл проверку, в имени зоны опечатка или запрос ушёл на не тот IP.
Проверьте список загруженных зон, синтаксис конфига и SOA-ответ напрямую:
named-checkconf
nsd-checkconf /etc/nsd/nsd.conf
dig @192.0.2.10 example.org SOA +norecurse
TSIG bad key, bad signature, unknown key
Если имя ключа разное на primary и secondary, сервер увидит unknown key. Если имя и алгоритм совпали, но secret отличается, будет ошибка подписи. Ещё одна частая причина — лишние пробелы или переносы при копировании base64-секрета.
Проверьте три поля на обоих серверах:
nameили имя в блокеkey;algorithm;secret.
Для новых установок используйте hmac-sha256 или более сильные современные варианты, поддерживаемые обеими сторонами. Старые алгоритмы вроде hmac-md5 лучше не использовать без крайней необходимости совместимости.
Secondary не обновляется после изменения зоны
Самая частая причина — забыли увеличить SOA serial. Вторая — BIND9 не перечитал зону из-за ошибки синтаксиса. Третья — NOTIFY не проходит по firewall или не разрешён в allow-notify на NSD. Четвёртая — NSD запрашивает transfer, но primary отказывает из-за TSIG или ACL.
Порядок проверки простой:
- Проверить zone file через
named-checkzone. - Сравнить SOA serial на primary и secondary через
dig. - Проверить логи BIND9 и NSD.
- Проверить TCP-доступность primary:53 со стороны secondary.
- Вручную запустить transfer на NSD и посмотреть статус зоны.
Безопасная ротация TSIG-ключа
TSIG-ключи тоже нужно периодически менять: при увольнении администратора, утечке конфигурации, переносе DNS на другую площадку или просто по внутренней политике безопасности. Главное — не ломать transfer резким удалением старого ключа.
Безопасный сценарий такой:
- Сгенерировать новый ключ, например
axfr-example-key-2026. - Добавить новый ключ на primary и secondary, не удаляя старый.
- Переключить
also-notifyиrequest-xfrна новый ключ. - Проверить AXFR с новым ключом и обновление serial на secondary.
- Удалить старый ключ из конфигурации и снова проверить reload.
Если secondary несколько, переключайте их по одному. Так проще понять, где именно возникла ошибка, и не потерять все резервные authoritative NS одновременно.
Практические рекомендации для production DNS
- Не открывайте AXFR для
any. Даже если зона публичная, полный transfer должен быть доступен только вашим secondary. - Используйте TSIG для transfer и NOTIFY. IP-ACL полезен, но IP можно ошибочно переиспользовать, а TSIG проверяет именно владение ключом.
- Открывайте TCP/53 осознанно. Без TCP zone transfer не заработает, но разрешать его лучше только нужным источникам, если сервер не обязан принимать TCP от всех клиентов.
- Следите за SOA serial. Автоматизация DNS-as-code должна увеличивать serial предсказуемо, иначе secondary останутся на старой версии.
- Проверяйте не только primary, но и каждый public NS. Мониторинг должен опрашивать SOA serial на всех authoritative серверах.
- Храните TSIG secret как секрет, а не как обычный конфиг. Ограничьте права на файл, исключите его из публичных репозиториев и бэкапов с широким доступом.
- Документируйте, кто primary для каждой зоны. В аварии это экономит минуты, когда нужно понять, где менять записи.
Если вы отдельно делегируете технические подзоны, например dev.example.org или customers.example.org, полезно заранее продумать границу ответственности между командами. Практические нюансы такой схемы разобраны в материале про делегирование поддомена на отдельные NS.
А для новых проектов не забывайте, что надёжная DNS-схема начинается ещё на этапе владения доменом: корректные NS, доступ к панели регистратора, актуальные контакты и своевременное продление. Если домен только запускается, пригодится регистрация доменов с понятным управлением DNS.
Короткий чек-лист внедрения
- Выбрали primary и secondary, проверили, что они находятся на разных узлах или площадках.
- Сгенерировали TSIG через
tsig-keygen. - Добавили ключ в BIND9 и NSD с одинаковыми
name,algorithmиsecret. - На BIND9 настроили
allow-transfer,also-notifyиnotify yes. - На NSD настроили
allow-notifyиrequest-xfr. - Открыли TCP/53 между secondary и primary, проверили cloud firewall и локальный firewall.
- Проверили, что AXFR без TSIG не проходит, а с TSIG проходит.
- Сравнили SOA serial на primary и secondary.
- Добавили мониторинг serial и ошибок transfer в логи/алерты.
Связка BIND9 + NSD для authoritative DNS получается надёжной и понятной, если не оставлять zone transfer «как-нибудь потом». AXFR и IXFR — штатные инструменты DNS, но доступ к ним нужно ограничивать так же аккуратно, как доступ к панели управления доменом. TSIG не усложняет эксплуатацию радикально, зато убирает главный риск: случайно отдать полную зону постороннему клиенту или принять NOTIFY от неавторизованного источника.


