Раньше, по долгу службы, приходилось администрировать DNS сервера. И вот недавно вновь появилась такая необходимость — надо было настроить два авторитарных DNS (master + slave) для обслуживания зоны. Сервера должны были смотреть в интернет. Задача — запустить зону и обеспечить автоматическую, секюрную репликацию от master (192.168.0.1) к slave (192.168.0.2).
В качестве ОС однозначно решил использовать FreeBSD 7.0 RELEASE, а вот с выбором DNS сервера для такого ответственного задания, все было не так просто... Дело в том, что BIND я не считаю за DNS сервер которому можно было бы доверить держать зону выставленную в интернет. Это мое субъективное мнение. Просто я стараюсь держаться подальше от софта в котором с периодичностью раз в пол года находят дыры позволяющие удаленно заражать кеш, не говоря уже о проблемах с его производительностью. Был вариант использовать любимый и проверенный временем пакет djbdns (tinydns), но опять же что-то меня остановило. Все хорошо в софте от djb, но развития больше нет — не пишет djb обновлений ни для djbdns ни для qmail, да и как то не хотелось снова замарачиваться с настройкой daemontools.
Выбор пал на авторитарный DNS сервер NSD. Честно сказать я давно присматривался с этому серверу. Недавно снова обратил свое внимание, когда вышел его брат, DNS ресольвер Unbound. Почитав мануалы на оба этих продукта, пришел в выводу, что не все так грустно в мире DNS, и что у djbdns появилась достойная замена.
С архитектурной точки зрения NSD — это исключительно авторитарный DNS сервер. Он не обслуживает рекурсивные клиентские запросы и ни чего не кеширует. Так же из плюсов стоит отметить его маленькие размеры, скромное потребление ресурсов и большую скорость работы. На счет показателей скорости, сошлюсь на результаты тестов которые не так давно проводил Kris Kennaway http://people.freebsd.org/~kris/scaling/bind-nsd.png Подсчитать же количество потребляемых ресурсов, исходя из размеров зоны, можно здесь: http://www.nlnetlabs.nl/projects/nsd/nsd-memsize.html Что же касается минусов, то стоит отметить ограниченную функциональность. Нет никаких view'ов — хочешь чтобы кто-то видел зону так, а кто-то другой по-другому - запускай второй NSD с его данными и разруливай доступ на фаерволе. Нет динамических обновлений. Нет точной статистики по загруженности — только аналог BIND'овских NSTATS и XSTATS которые выводятся в лог файл (зато в последнюю версию BIND аж, таки свой веб сервер встроили чтобы статистику показывать). Если нужна детальная статистика того кто, что и сколько — разработчики предлагают использовать для этого сторонние утилиты для прямого анализа трафика сервера.
В общем быстрого взгляда на опции конфигурации достаточно чтобы понять, что можно сделать с помощью NSD, а что не выйдет. Опций мало, все очень просто.
Так или иначе, мне BIND'овских извращений не надо. Мне надо чтобы работало.
Решено — ставим NSD!
Установка
На момент написания этой статьи, в портах была доступна версия 3.0.7. На всякий случай упомяну процедуру обновления портов. Для версий FreeBSD начиная с 6.2, это удобно делать через portsnap:
# portsnap fetch
# portsnap extract
После обновления портов, ставим NSD традиционным методом:
# cd /usr/ports/dns/nsd
# make install clean
При первой установке, порт предлагает выбрать несколько опций конфигурации. По-умолчанию выбран вполне разумный набор, с которым можно согласиться. Опции же такие:
Options for nsd 3.0.7
[ ] ROOT_SERVER Configure NSD as a root server
[X] LARGEFILE Enable support for large files
[X] IPV6 Enable IPv6 support
[X] DNSSEC Enable DNSSEC
[ ] BIND8_STATS Enable BIND8 like NSTATS & XSTATS
[ ] CHECKING Enable internal runtime checks
[X] TSIG Enable TSIG support
[ ] NSEC3 Enable NSEC3 support
[ ] NSID Enable NSID support
[X] DOCFILES Enable PORTDOCS
ROOT_SERVER — по-умолчанию NSD не разрешает запускать на себе корневую зону. Опция включает такую функциональность.
LARGEFILE - не берусь прокомментировать. В README эта опция описана как "Disable large file support (64 bit file lengths). Makes off_t a 32bit length during compilation" По-умолчанию включена.
DNSSEC - включает функциональность позволяющую подписывать DNS сообщения между серверами на основе шифрования с открытым ключом и использовать другие возможности DNSSEC.
CHECKING - полезно для debug, дополнительные внутренние проверки во время работы. Снижает производительность.
TSIG - включает функциональность позволяющую подписывать DNS сообщения между серверами на основе шифрования с общим симметричным ключом.
NSEC3 - экспериментальное расширение DNSSEC (непонялчтотакое =) не надо в общем)
NSID - экспериментальное расширение позволяющее вставлять в каждый ответ DNS сервера метку однозначно идентифицирующую DNS сервер. Используется для debug.
DOCFILES - в /usr/loca/share/doc/nsd будет установлен набор полезных руководств.
Компиляция происходит очень быстро — сервер маленький. Через пару минут порт будет собран и установлен.
nsd - the daemon itself
nsdc - a shell script to control the daemon
zonec - zone compiler
nsd-notify - a simple C program to send outbound notifies
nsd-xfer - a program to receive zones from a master server using AXFR
from the command line.
nsd-checkconf - simple C program to check nsd.conf before use.
nsd-patch - simple program that cleans IXFR changes back to zone files.
Главные инструменты с чем придется работать:
nsdc - главный интерфейс для локального управления демоном
(аналог BIND'овской ndc)
nsd-checkconf - проверяет корректность конфигурации nsd.conf
# nsdc
Usage: nsdc [-c configfile] {start|stop|reload|rebuild|restart|
running|update|notify|patch}
options:
-c configfile Use specified configfile (default:
/usr/local/etc/nsd/nsd.conf)
commands:
start Start nsd server.
stop Stop nsd server.
reload Nsd server reloads database file.
rebuild Compile database file from zone files.
restart Stop the nsd server and start it again.
running Prints message and exit nonzero if server not running.
update Try to update all slave zones hosted on this server.
notify Send notify messages to all secondary servers.
patch Merge zone transfer changes back to zone files.
В процессе установки не создается никаких новых пользователей. NSD сразу же компилится так, чтобы запускаться от имени пользователя bind который уже присутствует в системе
Это все, что касается установки из порта. Далее, идет настройка.
Настройка
Как и каждый правильный демон, NSD требует к себе уважения. Это означает, что его хозяину надо прочитать man nsd.conf, составить этот nsd.conf и составить файлы данных зон. Синтаксис nsd.conf (файла конфигурации NSD) отличается от того, что принято в BIND. Синтаксис файлов зон такой же как и в BIND. NSD может работать в chroot окружении. Я поленился делать jail для запуска NSD и для большей секюрности решил использовать этот chroot. По умолчанию chroot не задействован.
Далее пошаговое описание настроек сделаных на master сервере
Стартовый скрипт запуска /usr/local/etc/rc.d/nsd.sh подправляем, для того чтобы указать на новое расположение nsd.pid:
$TTL 1800 ;minimum ttl
domain.su. IN SOA ns1.domain.su. hostmaster.domain.su.(
2008062414 ;serial
3600 ;refresh
9600 ;retry
180000 ;expire
600 ;negative ttl
)
NS ns1.domain.su.
NS ns2.domain.su.
MX 10 mail
A 127.0.0.24
ns1 A 192.168.0.1
ns2 A 192.168.0.2
www A 127.0.0.24
ftp A 127.0.0.26
mail A 127.0.0.27
После создания nsd.conf и файла зоны, необходимо выполнить:
# nsd-checkconf /usr/local/etc/nsd/nsd.conf
Если нет сообщений об ошибках то создаем базу nsd.database в которой собственно и будут храниться данные о записях зоны:
# nsdc rebuild
zonec: reading zone "domain.su".
zonec: processed 8 RRs in "domain.su".
zonec: done with 0 errors.
После этого база /usr/local/etc/nsd/data/nsd.database будет создана.
Вносим в /etc/rc.conf строку nsd_enable="YES" и запускаем сервер:
После создания nsd.conf и файла зоны, необходимо выполнить:
# nsd-checkconf /usr/local/etc/nsd/nsd.conf
Если нет сообщений об ошибках то создаем базу nsd.database в которой собственно и будут храниться данные о записях зоны:
# nsdc rebuild
zonec: reading zone "domain.su".
warning: slave zone domain.su with no zonefile './slave/domain.su'
(No such file or directory) will force zone transfer.
zonec: processed 0 RRs in "domain.su".
zonec: done with 0 errors.
После этого база /usr/local/etc/nsd/data/nsd.database будет создана
Вносим в /etc/rc.conf строку nsd_enable="YES" и запускаем сервер:
Все в порядке — slave работает. Стоит проверить ps auxw и /var/log/nsd.log.
Последний шаг чтобы убедиться, что репликация между master и slave происходит как надо - заходим на master, открываем текстовый файл зоны /usr/local/etc/nsd/zones/master/domain.su и меняем там строку с серийным номером. Сохраняем файл зоны и выполняем:
# nsdc rebuild
# nsdc reload
Эта процедура пересоздает базу nsd.database на master (вносит туда изменения из отредактированного файла зоны) и отправляет сообщение NOTIFY на slave. Получив такое сообщение, slave запросит произвести AXFR передачу с master (192.168.0.1) и сохранит полученные данные в ixfr.db. Это важный момент! На slave база ixfr.db является своего рода логом транзакций полученных с master. Сразу после этого slave может обслуживать запросы. Текстовые данные пока еще НЕ созданы в файле ./zones/slave/domain.su
Последний штрих который необходимо сделать на slave сервере — внести в crontab root'a выполнение такой команды:
55 * * * /usr/local/sbin/nsdc patch
Команда nsdc patch выполняет две операции: 1 Переносит данные из лога ixfr.db в базу nsd.database, после чего удаляет лог. 2 Создает текстовые файлы с данными зоны в ./zones/slave/domain.su
Можно было бы не писать, но все же упомяну - все дальнейшие изменения в записях зоны вносятся в текстовый файл ./zones/master/domain.su на master сервере, после чего для перестройки базы и ее репликации на slave, выполняется тот же самый цикл команд:
# nsdc rebuild
# nsdc reload
Замечания
Почитав файлы README и NSD-FOR-BIND-USERS из комплекта поставки NSD удалось просветлиться по поводу таких моментов:
То, является ли зона типа master или типа slave определяется директивой request-xfr - у master ее нет, у slave она должна быть.
NSD master не поддерживает инкрементные передачи IXFR, поддерживаются только полные AXFR передачи. Если мастер (как в данном примере) работает под NSD, то в конфиге slave появляется request-xfr: AXFR 192.168.0.1 master-slave.domain.su
Директива provide-xfr на master эквивалентна директивам allow-transfer и server для BIND
В BIND ассоциация TSIG ключей происходит с IP сервера с которым производится коммуникация. В NSD TSIG ключи ассоциируются с ALC записями и соответствующие ключи используются при проведении различных запросов/ответов. Таким образом при работе с одним сервером можно применять одни ключи для оповещении о изменении зоны, и другие ключи при передаче данных зоны (своя пара для notify; allow-notify и своя для provide-xfr; request-xfr)!
На TSIG запросы отсылаются TSIG ответы.
В отличии от BIND, где адреса slave серверов определяются непосредственно из данных зоны (какие NS там указаны, такие значит у зоны slave), в NSD это определяется только из настроек в nsd.conf (кто указан в параметрах notify - тот и slave).
xfrd.state - файл-состояния используемый на slave для отслеживания истечения срока годности записей slave зоны.