UMGUM.COM 

NSD ( Настраиваем спарку легковесных авторитарных DNS-серверов. )

20 мая 2014  (обновлено 1 августа 2019)

OS: "Linux Debian 7/8/9/10", "Linux Ubuntu 16/18 LTS".
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", от имени которого предполагается запускать сервис 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="

Обращаю внимание на то, что в процедуре проверки 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

DNS-сервер NSD использует формат файлов описаний зон унифицированный с "Bind9" и может использовать файлы такового без изменений. Составим простейший файл описания зоны:

# mkdir -p /var/lib/nsd/master
# 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

Файл описания обратного резольвинга (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

Проверяем синтаксис конфигурационного файла сервера и файла описания зоны доменных имён:

# 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

По завершению конфигурирования ограничиваем доступ к файлам сервиса посторонним:

# chown -R nsd:nsd /etc/nsd /var/lib/nsd
# chmod -R o-rwx /etc/nsd /var/lib/nsd

Запускаем или перезапускаем сервис NSD:

# systemctl restart nsd
# systemctl status nsd

В дальнейшем после каждого изменения файлов описания зон сервис перезапускать нет необходимости - достаточно указать ему перечитать конфигурацию:

# nsd-control reload
# 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

Настройка вторичного (slave) NS-сервера.

Установка аналогична первичному. Настройки файлов описания зон доменных имён не требуется - достаточно указать на их источник:

# mkdir -p /var/lib/nsd/slave
# 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

Защищаем от посторонних файлы, проверяем синтаксическую корректность конфигурации и перезапускаем сервис:

# 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

Проверяем, успешно ли запустился сервис и слушает ли он выделенные сетевые порты:

# systemctl status 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.

Аналогично проверке первичного NS-сервера запрашиваем расширенное описание обслуживаемого доменного имени со вторичного DNS-сервера:

# host -a example.net 10.20.40.50


Заметки и комментарии к публикации:


Оставьте свой комментарий ( выразите мнение относительно публикации, поделитесь дополнительными сведениями или укажите на ошибку )