Apps: NSD.
Задача: завести два (и более) связанных в единую схему высокой доступности авторитарных DNS-сервера, отвечающих за поддержание сопоставлений FQDN и IP определённых доменных зон, без необходимости обработки рекурсивных запросов пользователей.
Для решения поставленной задачи отлично подходит легковесный DNS-сервер NSD ("Name Server Daemon"), разработанный в качестве только ответственного сервера (то есть, не обслуживающий рекурсивные запросы пользователей и кэширование таковых).
Отмечу, что NSD не имеет функционала различного представления зон в зависимости источника запроса, реализованного в "Bind9" через секцию "view", например - в связи с этим, при необходимости, для публичных и локальных доменных зон придётся заводить отдельные группы серверов. Также, насколько я уловил, NSD пока не поддерживает обновления доменных зон посредством протокола DDNS ("Dynamic DNS") - доступна только частичная автоматизация посредством дистрибутивной утилиты "nsd-control". Ну и журналирование со статистикой у NSD откровенно слабоваты, хотя для работы корректно настроенного сервиса достаточны.
Установка DNS-сервера NSD.
Инсталлируем пакет приложений:
# aptitude install nsd
Установленные приложения и утилиты, с которыми придётся работать:
nsd - непосредственно DNS-сервер;
nsd-checkconf - утилита проверки синтаксиса основного конфигурационного файла;
nsd-checkzone - утилита проверки синтаксиса файлов описания зон доменных имён;
nsd-control - утилита управления.
nsd-checkconf - утилита проверки синтаксиса основного конфигурационного файла;
nsd-checkzone - утилита проверки синтаксиса файлов описания зон доменных имён;
nsd-control - утилита управления.
В процессе установки в системе автоматически создаётся непривилегированный пользователь "nsd", от имени которого предполагается запускать сервис NSD.
Также при развёртывании APT-дистрибутива автоматически генерируется набор SSL-сертификатов для аутентификации при подключении к NSD утилиты управления "nsd-control" - по умолчанию это возможно без явных настроек через сетевой интерфейс локальной петли "127.0.0.1". При их отсутствии или просто для профилактики можно запустить утилиту "nsd-control-setup" создающую сертификаты (это не деструктивная операция, существующие файлы не меняются).
Подготовка TSIG-ключей для межсерверных XFR-запросов.
Учитывая то, что наши NS-серверы обслуживают интернет-запросы и связываются между собой через неконтролируемую сетевую инфраструктуру, предпримем минимально необходимые меры безопасности. Заставим сервера при транзакциях обмена сведениями об изменениях описаний зон доменных имён (XFR, "трансфер зон") использовать механизм подписей TSIG-ключ ("Transaction SIGnature") (это нужно для того, чтобы на место деактивированного тем или иным образом NS-сервера схемы взаимодействий нельзя было бы просто подставить NS-сервер злоумышленника, могущего внести путаницу в работе инфраструктуры).
Неоднократно встречал во вполне официальных инструкциях и сам бездумно использовал замысловатые схемы создания TSIG-ключей для простейшей аутентификации между NS-серверами посредством специализированных утилит вроде "dnssec-keygen" с последующим вычленением из полученных файлов конфигураций "магической" ключевой строчки. На самом деле в этом нет никакой необходимости - в этом качестве может выступать любая уникальная ASCII-текстовая строка:
# dd if=/dev/urandom of=/dev/stdout count=1 bs=32 status=none | base64
Используя полученную уникальную текстовую строку заготовим конфигурационный файл описания TSIG-ключа, который в последствии применим для связи всех участников схемы взаимодействия:
# vi /etc/nsd/ns-ns2.example.net.key
# TSIG-ключ для подписания XFR-транзакций между первичным и вторичными DNS-серверами
key:
name: "ns-ns2.example.net.key"
algorithm: hmac-sha256
secret: "ef6...+2D4="
key:
name: "ns-ns2.example.net.key"
algorithm: hmac-sha256
secret: "ef6...+2D4="
Обращаю внимание на то, что в процедуре проверки TSIG используются временные метки и в случае сильного расхождения часов на серверах таковая может сбоить - потому не забываем о наладке синхронизации с сервисами точного времени.
Настройка первичного (master) NS-сервера.
В качестве главного конфигурационного файла, при отсутствии такового, можно воспользоваться заготовкой из сопроводительной документации (/usr/share/doc/nsd/examples/nsd.conf.sample.gz), однако у меня за несколько лет сформировался минимально необходимый конфигурационный файл, который я повсеместно использую:
# vi /etc/nsd/nsd.conf
# Описание конфигурации DNS-сервера как такового
server:
ip-address: 0.0.0.0
ip4-only: yes
port: 53
round-robin: yes
identity: ns.example.net
hide-version: yes
server-count: 2
reuseport: yes
username: nsd
zonedir: /var/lib/nsd
pidfile: /run/nsd/nsd.pid
logfile: /var/log/nsd.log
verbosity: 2
# Добавляем описание TSIG-ключа
include: /etc/nsd/ns-ns2.example.net.key
# Параметры обслуживания зоны доменных имён
zone:
name: example.net
zonefile: ./master/example.net.zone
# for Slave "ns2.example.net"
notify: 10.20.40.50 NOKEY
provide-xfr: 10.20.40.50 ns-ns2.example.net.key
zone:
name: 20.10.in-addr.arpa
zonefile: ./master/20.10.in-addr.arpa.zone
# for Slave "ns2.example.net"
notify: 10.20.40.50 NOKEY
provide-xfr: 10.20.40.50 ns-ns2.example.net.key
server:
ip-address: 0.0.0.0
ip4-only: yes
port: 53
round-robin: yes
identity: ns.example.net
hide-version: yes
server-count: 2
reuseport: yes
username: nsd
zonedir: /var/lib/nsd
pidfile: /run/nsd/nsd.pid
logfile: /var/log/nsd.log
verbosity: 2
# Добавляем описание TSIG-ключа
include: /etc/nsd/ns-ns2.example.net.key
# Параметры обслуживания зоны доменных имён
zone:
name: example.net
zonefile: ./master/example.net.zone
# for Slave "ns2.example.net"
notify: 10.20.40.50 NOKEY
provide-xfr: 10.20.40.50 ns-ns2.example.net.key
zone:
name: 20.10.in-addr.arpa
zonefile: ./master/20.10.in-addr.arpa.zone
# for Slave "ns2.example.net"
notify: 10.20.40.50 NOKEY
provide-xfr: 10.20.40.50 ns-ns2.example.net.key
DNS-сервер NSD использует формат файлов описаний зон унифицированный с "Bind9" и может использовать файлы такового без изменений. Составим простейший файл описания зоны:
# mkdir -p /var/lib/nsd/master
# vi /var/lib/nsd/master/example.net.zone
# vi /var/lib/nsd/master/example.net.zone
$ORIGIN example.net.
$TTL 3600 ; TTL (1 hour)
; SOA
@ IN SOA example.net. admin.example.net. (
2014052101 ; serial
7200 ; refresh in sec. (1 hour)
900 ; retry in sec. (15 minutes)
1209600 ; expire in sec. (5 weeks 6 days 16 hours)
3600 ; negative ttl (1 hour)
);
; NS - name servers
IN NS ns.example.net.
IN NS ns2.example.net.
; A - for name servers
ns IN A 10.20.30.40
ns2 IN A 10.20.40.50
; A - address records
@ IN A 10.20.100.200
www IN A 10.20.100.200
mx IN A 10.20.10.20
; MX - mail exchange records
example.net. IN MX 10 mx.example.net.
; SPF - additional records
example.net. IN TXT "v=spf1 ipv4:10.20.10.20 ~all"
example.net. IN SPF "v=spf1 ipv4:10.20.10.20 ~all"
; EOF
$TTL 3600 ; TTL (1 hour)
; SOA
@ IN SOA example.net. admin.example.net. (
2014052101 ; serial
7200 ; refresh in sec. (1 hour)
900 ; retry in sec. (15 minutes)
1209600 ; expire in sec. (5 weeks 6 days 16 hours)
3600 ; negative ttl (1 hour)
);
; NS - name servers
IN NS ns.example.net.
IN NS ns2.example.net.
; A - for name servers
ns IN A 10.20.30.40
ns2 IN A 10.20.40.50
; A - address records
@ IN A 10.20.100.200
www IN A 10.20.100.200
mx IN A 10.20.10.20
; MX - mail exchange records
example.net. IN MX 10 mx.example.net.
; SPF - additional records
example.net. IN TXT "v=spf1 ipv4:10.20.10.20 ~all"
example.net. IN SPF "v=spf1 ipv4:10.20.10.20 ~all"
; EOF
Файл описания обратного резольвинга (PTR-записи) зоны доменных имён составляется примерно так:
# vi /var/lib/nsd/master/20.10.in-addr.arpa.zone
$ORIGIN 20.10.in-addr.arpa.
$TTL 3600 ; TTL (1 hour)
; SOA
@ IN SOA example.net. admin.example.net. (
2014052101 ; serial
7200 ; refresh in sec. (1 hour)
900 ; retry in sec. (15 minutes)
1209600 ; expire in sec. (5 weeks 6 days 16 hours)
3600 ; negative ttl (1 hour)
);
; NS - name servers
IN NS ns.example.net.
IN NS ns2.example.net.
; PTR - IP address records
10.20.30.40 IN A ns.example.net.
10.20.40.50 IN A ns2.example.net.
10.20.10.20 IN A mx.example.net.
10.20.100.200 IN A example.net.
10.20.100.200 IN A www.example.net.
; EOF
$TTL 3600 ; TTL (1 hour)
; SOA
@ IN SOA example.net. admin.example.net. (
2014052101 ; serial
7200 ; refresh in sec. (1 hour)
900 ; retry in sec. (15 minutes)
1209600 ; expire in sec. (5 weeks 6 days 16 hours)
3600 ; negative ttl (1 hour)
);
; NS - name servers
IN NS ns.example.net.
IN NS ns2.example.net.
; PTR - IP address records
10.20.30.40 IN A ns.example.net.
10.20.40.50 IN A ns2.example.net.
10.20.10.20 IN A mx.example.net.
10.20.100.200 IN A example.net.
10.20.100.200 IN A www.example.net.
; EOF
Проверяем синтаксис конфигурационного файла сервера и файла описания зоны доменных имён:
# nsd-checkconf /etc/nsd/nsd.conf
# nsd-checkzone example.net /var/lib/nsd/master/example.net.zone
# nsd-checkzone 20.10.in-addr.arpa /var/lib/nsd/master/20.10.in-addr.arpa.zone
# nsd-checkzone example.net /var/lib/nsd/master/example.net.zone
# nsd-checkzone 20.10.in-addr.arpa /var/lib/nsd/master/20.10.in-addr.arpa.zone
По завершению конфигурирования ограничиваем доступ к файлам сервиса посторонним:
# chown -R nsd:nsd /etc/nsd /var/lib/nsd
# chmod -R o-rwx /etc/nsd /var/lib/nsd
# chmod -R o-rwx /etc/nsd /var/lib/nsd
Запускаем или перезапускаем сервис NSD:
# systemctl restart nsd
# systemctl status nsd
# systemctl status nsd
В дальнейшем после каждого изменения файлов описания зон сервис перезапускать нет необходимости - достаточно указать ему перечитать конфигурацию:
# nsd-control reload
# nsd-control status
# nsd-control status
После считывания описаний зон производится компиляция текстовых данных в двоичный формат и всё это размещается в оперативной памяти, что обеспечивает максимальную скорострельность сервиса.
Проверяем, заступил ли NSD на прослушивание TCP/UDP-портов:
# netstat -apn | grep nsd
Журнал событий небогат сведениями (в отличии от "Bind9"), но посматривать в него полезно:
# tail -f /var/log/nsd.log
Финальная проверка - запрос расширенного описания доменного имени с конкретного DNS-сервера:
# host -a example.net 10.20.30.40
# dig example.net @10.20.30.40
# dig example.net @10.20.30.40
Настройка вторичного (slave) NS-сервера.
Установка аналогична первичному. Настройки файлов описания зон доменных имён не требуется - достаточно указать на их источник:
# mkdir -p /var/lib/nsd/slave
# vi /etc/nsd/nsd.conf
# vi /etc/nsd/nsd.conf
server:
ip-address: 0.0.0.0
ip4-only: yes
port: 53
round-robin: yes
identity: ns2.example.net
hide-version: yes
server-count: 2
username: nsd
zonedir: /var/lib/nsd
pidfile: /run/nsd/nsd.pid
logfile: /var/log/nsd.log
verbosity: 2
include: /etc/nsd/ns-ns2.example.net.key
zone:
name: example.net
zonefile: ./slave/example.net.zone
# for Master "ns.example.net"
allow-notify: 10.20.30.40 NOKEY
request-xfr: AXFR 10.20.30.40 ns-ns2.example.net.key
zone:
name: 20.10.in-addr.arpa
zonefile: ./slave/20.10.in-addr.arpa.zone
# for Master "ns.example.net"
allow-notify: 10.20.30.40 NOKEY
request-xfr: AXFR 10.20.30.40 ns-ns2.example.net.key
ip-address: 0.0.0.0
ip4-only: yes
port: 53
round-robin: yes
identity: ns2.example.net
hide-version: yes
server-count: 2
username: nsd
zonedir: /var/lib/nsd
pidfile: /run/nsd/nsd.pid
logfile: /var/log/nsd.log
verbosity: 2
include: /etc/nsd/ns-ns2.example.net.key
zone:
name: example.net
zonefile: ./slave/example.net.zone
# for Master "ns.example.net"
allow-notify: 10.20.30.40 NOKEY
request-xfr: AXFR 10.20.30.40 ns-ns2.example.net.key
zone:
name: 20.10.in-addr.arpa
zonefile: ./slave/20.10.in-addr.arpa.zone
# for Master "ns.example.net"
allow-notify: 10.20.30.40 NOKEY
request-xfr: AXFR 10.20.30.40 ns-ns2.example.net.key
Защищаем от посторонних файлы, проверяем синтаксическую корректность конфигурации и перезапускаем сервис:
# chown -R nsd:nsd /etc/nsd /var/lib/nsd
# chmod -R o-rwx /etc/nsd /var/lib/nsd
# nsd-checkconf /etc/nsd/nsd.conf
# systemctl restart nsd
# chmod -R o-rwx /etc/nsd /var/lib/nsd
# nsd-checkconf /etc/nsd/nsd.conf
# systemctl restart nsd
Проверяем, успешно ли запустился сервис и слушает ли он выделенные сетевые порты:
# systemctl status nsd
# netstat -apn | grep nsd
# netstat -apn | grep nsd
Сразу после запуска или перезапуска вторичный сервер попытается запросить посредством протокола XFR у "мастера" описание обслуживаемых зон доменных имён. Далее приведён пример уведомлений в журнале событий о сбое запроса (по причине ненастроенных правил аутентификации) и последующих уведомлений об успешной синхронизации:
# tail -f /var/log/nsd.log
... notice: nsd starting (NSD 4.1.17)
... error: xfrd: zone example.net received error code REFUSED from 10.20.30.40
....
... info: zone example.net serial 0 is updated to 2018082202.
... info: zone example.net serial 2018082202 is updated to 2019073001.
... error: xfrd: zone example.net received error code REFUSED from 10.20.30.40
....
... info: zone example.net serial 0 is updated to 2018082202.
... info: zone example.net serial 2018082202 is updated to 2019073001.
Аналогично проверке первичного NS-сервера запрашиваем расширенное описание обслуживаемого доменного имени со вторичного DNS-сервера:
# host -a example.net 10.20.40.50