Bind: Внешний DNS сервер

Перед трансфером зоны с одного регистратора на другого выяснилось, что сохраняются только NS записи, которые указывают на DNS серверы. Все остальные записи типа A, CNAME, MX, TXT, SRV теряются. Потому было решено поднять свои собственные DNS сервера для обслуживания доменной зоны (так сказать транзитные сервера).

ЗАЧЕМ?

Вам это может пригодиться при трансферах так и если захотите захостить DNS на своих серверах. Преимуществ это никаких не дает, но в моем случае решает проблему с трансфером, чтобы выполнить задачу без даунтайма.

ТЕОРИЯ

DNS сервер может работать в двух ролях.

Рекурсивный сервер — обычно используется чтобы резолвить доменные адреса в IP адреса. Если forwarders не задан, то информация будет запрашиваться с DNS серверов указанных в /etc/resolv.conf.

Авторитетный сервер — используется для отдачи/обслуживания доменных зон указанных в конфигурации сервера. Все остальные запросы будут отклоняться. Настраивать будем именно этот вариант.

Для синхронизации зоны с подчиненным сервером надо указать IP адрес подчиненного сервера на стороне мастера и IP адрес мастера на стороне подчиненного. Синхронизация выполняется путем AXFR запроса, который дампит всю доменную зону.

Поднимать следует сразу два сервера и желательно гео распределенных. В моем случае мастер располагается на виртуальной машине amazon в Сиеттле, а второй на виртуальной машине руцентра в Москве. Если упадет мастер, то все запросы отправятся на подчиненный сервер.

Что еще стоит знать так это то, что не надо комбинировать авторитетный и рекурсивный сервер поскольку в этом случае другие DNS серверы в мире будут видеть, что сервер работает в режиме рекурсии и не будут кэшировать зону. Я допустил эту ошибку и когда один из системных администраторов перенастраивал фаервол, то забыл открыть порты для DNS в итоге в ту же секунду упала вся зона. Проверка на nslookup показала, что в таком случае другие DNS серверы просто передавали запрос на next-server, а next-server это наш сервер. Также не стоит комбинировать с внутренним DNS сервером поскольку если какому-то доменному адресу задать внешний IP (ресурс имеет один и тот же доменный адрес для внешки и внутрянки), то такие запросы будут блокироваться маршрутизатором определяясь как атака типа DNS Rebind. Так что лучше отделить серверы для обслуживания внутренних сетей от серверов для обслуживания сети интернет.

НАСТРОЙКА МАСТЕРА

Настройка /etc/bind/named.conf.options:

options {
	version "unknown";
	directory "/var/cache/bind";
	dnssec-validation auto;
	auth-nxdomain no;
	listen-on-v6 { any; };
	recursion no;
};

Добавим конфигурацию своей зоны в /etc/bind/named.conf.default-zones:

zone "." {
        type hint;
        file "/etc/bind/db.root";
};

zone "localhost" {
        type master;
        file "/etc/bind/db.local";
};

zone "mydomain.com" {
        type master;
        file "/etc/bind/mydomain.zone";
        notify yes;
        also-notify { slave_ip; };
        allow-transfer { slave_ip; };
};

zone "127.in-addr.arpa" {
        type master;
        file "/etc/bind/db.127";
};

zone "0.in-addr.arpa" {
        type master;
        file "/etc/bind/db.0";
};

zone "255.in-addr.arpa" {
        type master;
        file "/etc/bind/db.255";
};

Настроим зону в /etc/bind/mydomain.zone:

# ttl 4 часа
$TTL 14400
@       IN      SOA     mydomain.com root.mydomain.com (
                        2200020920      ; serial
                        10800           ; refresh
                        3600            ; retry
                        604800          ; expire
                        14400 )         ; minimum
@                       IN      NS      master_ip
@                       IN      NS      slave_ip
mydomain.com.           IN      A       master_ip
redmine                 IN      A       redmine_ip
office                  IN      A       blog_ip
...

Здесь serial надо менять каждый раз когда меняется файл зоны. Я записываю его в таком формате:
2200 — это час и минута
02 — число
09 — месяц
20 — год

Таким образом можно узнать когда файл зоны был модифицированы в последний раз и сам serial получается каждый раз уникальным. Если его не менять, то сервер не будет считывать файл зоны и будет отдавать, то что есть в кеше.
refresh — задает время через которое другие серверы могут запросить информацию о зоне. Установлено в 3 часа.
retry — если при запросе информации о зоне сервер был недоступен, то серверы могут повторить запрос через 1 час.
expire — если сервер не отвечает на запросы уже 168 часов (неделя), то другие серверы могут удалить у себя информацию о зоне.
minimum — если в зоне произошли изменения (например изменилась запись), то старую можно заменить через 4 часа. Потому оно должно либо совпадать с значением TTL либо быть меньше.

Перезапускаем bind и проверяем все ли работает:

systemctl restart bind9

nslookup mydomain.com master_ip
Server:         master_ip
Address:        master_ip#53
Name:   mydomain.com
Address: master_ip

Если надо проверить отдачу например TXT записей, то выполняем host -t txt mydomain.com. Аналогичным образом можно проверить отдачу других записей.

НАСТРОЙКА СЛЕЙВА

Забирем зону с мастера:

scp username@master_ip:/etc/bind/mydomain.zone /etc/bind/

/etc/bind/named.conf.options настраиваем точно также как и на мастере. А вот настройка зоны будет немного отличаться /etc/bind/named.conf.default-zones:

...
zone "mydomain.com" {
        type slave;
        file "/etc/bind/mydomain.zone";
        masters { master_ip; };
}
...

Поскольку файлы слейва будут перезаписываться самим Bind, то надо выдать права доступа к файлу зоны:

chown bind:bind /etc/bind/mydomain.zone

Рестартуем и проверяем как проверяли мастера.

ТЕСТ ТРАНСФЕРА ЗОНЫ

Сперва проверим с слейва разрешает ли мастер выполнять AXFR запрос:

host -t axfr mydomain.com master_ip

Trying "mydomain.com"
Using domain server:
Name: master_ip
Address: master_ip#53
Aliases:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41084
;; flags: qr aa; QUERY: 1, ANSWER: 151, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;mydomain.com.                    IN      AXFR
...

Видим, что AXFR запрос проходит. Если нет, то ищите причину в /var/log/syslog.

Теперь проверка боем. Добавим тестовый хост на мастере в /etc/bind/mydomain.zone:

test	IN	A	8.8.8.8

Не забыаем инкрементировать serial:

1122040920      ; serial

И вместо рестарта выполним reload:

rndc reload

Теперь запрашиваем хост у слейва:

nslookup test.mydomain.com slave_ip

Server:         slave_ip
Address:        slave_ip#53
Name:   test.mydomain.com
Address: 8.8.8.8

Так же на стороне слейва в /var/log/syslog можем увидеть, что зона обновилась:

transfer of 'mydomain.com/IN' from master_ip#53: connected using slave_ip#20373
zone mydomain.com/IN: transferred serial 1122040920
transfer of 'mydomain.com/IN' from master_ip#53: Transfer status: success

ВОПРОСЫ

Зачем устанавливать TTL в 4 часа? Нельзя ли поменьше, чтобы изменения применялись быстрее?
Да, изменения будут применяться быстрее также как и обновляться кэш на других серверах во всем мире и если ваши DNS серверы упадут, то у вас будет время успеть поднять серверы пока не истек TTL. Мне кажется 4 часа для меня достаточно чтобы успеть поднять их.

Мне непонятно как другие серверы узнают о хостах в моей зоне. Почему слейв так не умеет?
Вы покупаете у регистратора домен. В настройках домена вы указываете адреса своих DNS серверов таким образом мировые корневые DNS серверы узнают о ваших DNS серверах. Далее скажем кто-то в индии запрашивает site.mydomain.com, тогда запрос идет к DNS серверу провайдера, оттуда к серверу корневому индии, оттуда к корневому серверу зоны .com, оттуда к DNS серверу регистратора, оттуда уже к вашему серверу. При всех последующих запросах ответы уже будут отдаваться из кеша DNS сервера провайдера. Слейв же так не может, потому что так могут только рекурсивные серверы (собственно эта цепочка запросов и называется рекурсивным запросом), а слейв является авторитетным сервером. Вот почему нужен трансфер зон между мастером и слейвом.

Можно ли другим серверам разрешать трансфер?
На свой страх и риск. Злоумышленники могут раскрыть всю вашу сетевую инфраструктуру одним AXFR запросом. Не сказать, что это прям таки критично, но лучше по возможности старайтесь минимизировать риски.

Почему dig mydomain.com показывает TTL отличный от установленного на моих серверах?
У разных серверов могут быть разные политики кэширования информации. В этом и кроется причина. Чтобы удостовериться в этом выполните dig +trace mydomain.com так вы проследите весь путь запроса.