В качестве ОС однозначно решил использовать FreeBSD 7.0 RELEASE, а вот с выбором DNS сервера для такого ответственного задания, все было не так просто... Дело в том, что BIND я не считаю за DNS сервер которому можно было бы доверить держать зону выставленную в интернет. Это мое субъективное мнение. Просто я стараюсь держаться подальше от софта в котором с периодичностью раз в пол года находят дыры позволяющие удаленно заражать кеш, не говоря уже о проблемах с его производительностью. Был вариант использовать любимый и проверенный временем пакет djbdns (tinydns), но опять же что-то меня остановило. Все хорошо в софте от djb, но развитие остановилось — не пишет djb обновлений ни для djbdns ни для qmail, да и как то не хотелось снова замарачиваться с настройкой daemontools.
Выбор пал на авторитарный DNS сервер NSD 3. Честно сказать я давно присматривался с этому серверу. Недавно снова обратил свое внимание, когда вышел его брат 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
Код: Выделить всё
# 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
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 сервер. Используется для дебага.
DOCFILES — в /usr/loca/share/doc/nsd будет установлен набор полезных руководств.
Компиляция происходит очень быстро — сервер маленький. Через пару минут порт будет собран и установлен.
Файлы устанавливаемые портом:
Код: Выделить всё
/usr/local/sbin
/usr/local/etc/nsd
/usr/local/man
/usr/local/man/man8
/usr/local/man/man5
/usr/local/sbin/nsd
/usr/local/sbin/zonec
/usr/local/sbin/nsdc
/usr/local/sbin/nsd-notify
/usr/local/sbin/nsd-checkconf
/usr/local/sbin/nsd-patch
/usr/local/sbin/nsd-xfer
/usr/local/man/man8
/usr/local/man/man8
/usr/local/man/man8
/usr/local/man/man8/nsd-notify.8
/usr/local/man/man8/nsd-checkconf.8
/usr/local/man/man8/nsd-patch.8
/usr/local/man/man8/nsd-xfer.8
/usr/local/man/man5/nsd.conf.5
/usr/local/etc/nsd/nsd.conf.sample
/usr/local/etc/rc.d/nsd.sh
/usr/local/share/doc/nsd/CREDITS
/usr/local/share/doc/nsd/ChangeLog
/usr/local/share/doc/nsd/LICENSE
/usr/local/share/doc/nsd/NSD-DATABASE
/usr/local/share/doc/nsd/NSD-DIFFFILE
/usr/local/share/doc/nsd/NSD-FOR-BIND-USERS
/usr/local/share/doc/nsd/README
/usr/local/share/doc/nsd/README.icc
/usr/local/share/doc/nsd/RELNOTES
/usr/local/share/doc/nsd/REQUIREMENTS
/usr/local/share/doc/nsd/TESTPLAN
/usr/local/share/doc/nsd/TODO
/usr/local/share/doc/nsd/UPGRADING
/usr/local/share/doc/nsd/coding-style
/usr/local/share/doc/nsd/differences.tex
Код: Выделить всё
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 требует к себе уважения. Это означает что его хозяину надо прочитать 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:
Код: Выделить всё
##pidfile=/var/run/${name}.pid
pidfile=/usr/local/etc/nsd/run/${name}.pid
Код: Выделить всё
[root@master /usr/local/etc/nsd]# ls -la
drwxr-xr-x 5 root wheel 512 Jun 24 18:22 .
drwxr-xr-x 5 root wheel 512 Jun 24 11:35 ..
drwxrwx--- 2 root bind 512 Jun 24 13:38 data
-r--r----- 1 root wheel 935 Jun 24 13:28 nsd.conf
drwxrwx--- 2 root bind 512 Jun 24 16:07 run
drwxr-x--- 4 root bind 512 Jun 24 11:50 zones
Код: Выделить всё
-rw-r--r-- 1 root bind 677 Jun 24 13:38 nsd.database
-rw-r--r-- 1 bind bind 1524 Jun 24 14:24 xfrd.state
Код: Выделить всё
-rw-r--r-- 1 bind bind 5 Jun 24 16:07 nsd.pid
Код: Выделить всё
drwxr-x--- 2 root bind 512 Jun 24 13:39 master
drwxr-x--- 2 root bind 512 Jun 24 12:37 slave
Код: Выделить всё
-rw-r--r-- 1 root bind 1163 Jun 24 13:38 domain.su
Код: Выделить всё
# dd if=/dev/urandom bs=16 count=1 2>/dev/null | openssl base64
KSVb40kv/CuHgTTvhKZ7Y5==
Код: Выделить всё
server:
chroot: "/usr/local/etc/nsd"
ip-address: 0.0.0.0
ip4-only: yes
database: "/usr/local/etc/nsd/data/nsd.database"
logfile: "/var/log/nsd.log"
server-count: 5
pidfile: "/usr/local/etc/nsd/run/nsd.pid"
zonesdir: "/usr/local/etc/nsd/zones"
difffile: "/usr/local/etc/nsd/data/ixfr.db"
xfrdfile: "/usr/local/etc/nsd/data/xfrd.state"
key:
name: "master-slave.domain.su"
algorithm: hmac-md5
secret: "KSVb40kv/CuHgTTvhKZ7Y5=="
zone:
name: "domain.su"
zonefile: "./master/domain.su"
notify: 192.168.0.2 master-slave.domain.su
provide-xfr: 192.168.0.2 master-slave.domain.su
Файл зоны domain.su на master такой (примерно):
Код: Выделить всё
$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-checkconf /usr/local/etc/nsd/nsd.conf
Код: Выделить всё
# nsdc rebuild
zonec: reading zone "domain.su".
zonec: processed 8 RRs in "domain.su".
zonec: done with 0 errors.
Вносим в /etc/rc.conf строку nsd_enable="YES" и запускаем сервер
Код: Выделить всё
# /usr/local/etc/rc.d/nsd.sh start
Код: Выделить всё
/usr/local/etc/nsd/run/nsd.pid
/usr/local/etc/nsd/data/xfrd.state
/var/log/nsd.log
Далее описание настроек сделаных на salve сервере:
Стартовый скрипт запуска /usr/local/etc/rc.d/nsd.sh подправляем для того, чтобы указать на новое расположение nsd.pid:
Код: Выделить всё
##pidfile=/var/run/${name}.pid
pidfile=/usr/local/etc/nsd/run/${name}.pid
Код: Выделить всё
[root@master /usr/local/etc/nsd]# ls -la
drwxr-xr-x 5 root wheel 512 Jun 24 18:22 .
drwxr-xr-x 5 root wheel 512 Jun 24 11:35 ..
drwxrwx--- 2 root bind 512 Jun 24 13:38 data
-r--r----- 1 root wheel 935 Jun 24 13:28 nsd.conf
drwxrwx--- 2 root bind 512 Jun 24 16:07 run
drwxr-x--- 4 root bind 512 Jun 24 11:50 zones
Код: Выделить всё
-rw-r--r-- 1 bind bind 604 Jun 24 19:09 ixfr.db
-rw-r--r-- 1 root bind 677 Jun 24 13:38 nsd.database
-rw-r--r-- 1 bind bind 1524 Jun 24 14:24 xfrd.state
Код: Выделить всё
-rw-r--r-- 1 bind bind 5 Jun 24 16:07 nsd.pid
Код: Выделить всё
drwxr-x--- 2 root bind 512 Jun 24 13:39 master
drwxr-x--- 2 root bind 512 Jun 24 12:37 slave
Конфигурационный файл nsd.conf на slave такой:
Код: Выделить всё
server:
chroot: "/usr/local/etc/nsd"
ip-address: 0.0.0.0
ip4-only: yes
database: "/usr/local/etc/nsd/data/nsd.database"
logfile: "/var/log/nsd.log"
server-count: 5
pidfile: "/usr/local/etc/nsd/run/nsd.pid"
zonesdir: "/usr/local/etc/nsd/zones"
difffile: "/usr/local/etc/nsd/data/ixfr.db"
xfrdfile: "/usr/local/etc/nsd/data/xfrd.state"
key:
name: "master-slave.domain.su"
algorithm: hmac-md5
secret: "KSVb40kv/CuHgTTvhKZ7Y5=="
zone:
name: "domain.su"
zonefile: "./slave/domain.su"
allow-notify: 192.168.0.1 master-slave.domain.su
request-xfr: AXFR 192.168.0.1 master-slave.domain.su
После создания nsd.conf и файла зоны, необходимо выполнить:
Код: Выделить всё
# nsd-checkconf /usr/local/etc/nsd/nsd.conf
Код: Выделить всё
# 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.
Вносим в /etc/rc.conf строку nsd_enable="YES" и запускаем сервер
Код: Выделить всё
# /usr/local/etc/rc.d/nsd.sh start
Код: Выделить всё
/usr/local/etc/nsd/run/nsd.pid
/usr/local/etc/nsd/data/xfrd.state
/var/log/nsd.log
Последний шаг чтобы убедиться, что репликация между master и slave происходит как надо - заходим на master, открываем текстовый файл зоны /usr/local/etc/nsd/zones/master/domain.su и меняем там строку с серийным номером. Сохраняем файл зоны и выполняем:
Код: Выделить всё
# nsdc rebuild
# nsdc reload
Последний штрих который необходимо сделать на slave сервере — внести в crontab root'a выполнение такой команды:
Код: Выделить всё
5 5 * * * /usr/local/sbin/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 зоны.
---
Прошу покомментировать/поспрашивать/поругать


В следующий раз напишу про unbound...
Разместил готовую статью здесь: http://www.lissyara.su/?id=1696