Как работает DNS

Рассмотрим как работает DNS и рассмотрим некоторую конфигурацию сервера BIND.

Система доменных имен

Рассмотрим адрес m.habr.com. M это доменный адрес третьего уровня, который говорит нам о том, что это адрес мобильной версии сайта. Habr это доменный адрес второго уровня, который обычно говорит о названии сайта, но это не всегда и не обязательно так. Com это адрес первого уровня, который обычно указывает на принадлежность сайта к определенному сектору (com — коммерческий, ru — русский и т.д.).
Далее когда мы набираем в браузере habr.com, то этот адрес преобразуется в IP-адрес 178.248.237.68 и уже по этому адресу происходит соединение клиента с сервером. Узнать IP-адрес сайта всегда можно с помощью утилиты nslookup:

C:\Users\igro>nslookup habr.com
╤хЁтхЁ:  UnKnown
Address:  192.168.1.1

Не заслуживающий доверия ответ:
╚ь :     habr.com
Address:  178.248.237.68

У каждого интернет-провайдера есть свой DNS сервер, который синхронизируется с вышестоящим DNS сервером. У каждой страны есть свой корневой DNS сервер, который занимается обслуживанием доменного адреса первого уровня (например .ru). В свою очередь этот корневой DNS соединяется с корневыми серверами других стран, чтобы получать информацию о доменных именах иностранных ресурсов. Таким образом любая страна может заблокировать у себя в стране информацию о какой-либо стране и тогда граждане этой страны не смогут попадать на сайты заблокированной страны (конечно легальными методами).
Также есть центральный корневой сервер, который знает информацию о всех ресурсах в мире и любой DNS сервер может подключиться к нему и получить необходимые данные. Сервер этот расположен ориентировочно где-то в США под надзором организации ICANN, который занимается контролем над доменными именами и IP-адресами во всем мире. Так что, если вам говорят, что интернет сеть полностью децентрализованная, то имейте ввиду, что это не совсем так и все таки есть способы как усложнить работу интернета в той или иной стране. Например, ICANN вполне может убрать информацию о зоне .ru с своих корневых серверов и тогда пользователи во всем мире не смогут попадать на сайты в домене .ru (кроме граждан самой страны). Таким образом вы даже дома можете поднять свой DNS сервер и получать данные с практически любого публичного DNS сервера (например, с сервера своего интернет-провайдера или с сервера Google 8.8.8.8, CloudFlare по адресу 1.1.1.1 или любых других). Получается примерно такая иерархия: DNS сервер пользователя получает данные с DNS публичных или провайдера, которые в свою очередь получают информацию от DNS серверов регистраторов, которые обмениваются данными с корневыми серверами стран, которые обмениваются данными с корневыми серверами ICANN.

Типы записей

В так называемых «файлах зоны» описываются записи указывающие на что либо. Рассматривать будем на примере IP версии 4 и только основные записи:

A (Address) - указывает на IP-адрес сервера т.е. если мы хотим, чтобы сайт открывался по доменному имени, то прописываем его адрес в A записи.
CNAME (Canonical Name) - это alias (псевдоним) и используется для переадресации. Например, есть сайт скажем myblog.ru и надо создать адрес www.myblog.ru, который будет открывать сайт по адресу myblog.ru, тогда создаем CNAME www для доменного адреса myblog.ru.
MX (Mail Exchange) - здесь надо указывать адрес сервера электронной почты и его приоритет (чем больше число, тем ниже приоритет) т.е. если хотите узнать есть ли у сайта свой почтовый сервер, то ищите именно эту запись.
NS (Name Server) - адрес DNS сервера обслуживающего данную зону. Под зоной обычно понимается домен второго уровня (например, myblog.ru).
PTR (Pointer) - указывает на сервер, который прописан в A записи. Обычно создается множество A записей, поскольку у одного сервера может быть множество доменных имен и создается один PTR для обратного соответствия. Скажем если есть два A записи www.myblog.ru и myblog.ru и PTR создан для myblog.ru, то при ping www.myblog.ru будет возвращаться ответ от myblog.ru. Обычно эта запись необязательна, но может потребоваться в некоторых случаях, например когда у вас хостится почтовый сервер. Ведь другие почтовые серверы резолвят PTR запись, чтобы убедится, что такой сервер реально существует.
SOA (Start Of Authority) - используется для указания зоны.
TXT (Text string) - еще одна необязательная запись, в которую можно записывать произвольную информацию, но опять таки пригодится при определенных условиях. Например для настройки Sender Policy Framework, если в вашей зоне есть MX запись.
SRV (Service locator) - указывает на определенные сервисы. Например раньше широко использовался при установке Jabber, где надо было указывать адрес сервера для его автоматического поиска клиентом.

Рассмотрим пример конфигурации BIND

Начнем с основной конфигурации named.conf:

options {
        version "unknown";
        listen-on-v6 port 53 { none; };
        directory       "/var/named";
        dump-file       "/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        memstatistics-file "/var/named/data/named_mem_stats.txt";
        forward first;
        forwarders {
                1.1.1.1;
                1.0.0.1;
        };
        allow-query     { 127.0.0.1; };
        allow-query-cache { 127.0.0.1; };
        allow-recursion { 127.0.0.1; };
        recursion yes;

        /* Path to ISC DLV key */
        bindkeys-file "/etc/named.iscdlv.key";

        managed-keys-directory "/var/named/dynamic";

        check-names master ignore;
        check-names slave ignore;
        check-names response ignore;
};

version — скрывает версию сервера.
listen-on-v6 — отключает поддержку IP версии 6.
forward first — сперва резолвит заправшиваемый адрес с помощью серверов, которые указаны в директиве forwarders и если адрес не будет найден, то начнет искать в своих файлах зоны.
allow-query — разрешает запросы с указанных адресов или сетей.
recursion — разрешает рекурсивные запросы т.е. если запрашиваемый адрес не был найден в своей зоне, то запрос отправляется дальше к другим DNS серверам по цепочке до тех пор, пока не будет найден адрес. Если выставить в no, то будет использоваться режим итерации, в котором DNS сервер, если не найдет адрес, то не отправит запрос к следующему серверу, а укажет DNS клиенту операционной системы, у какого DNS сервера можно найти информацию по этому адресу.
check-names — проверка имен хостов на соответствие правилам RFC. Обычно не используется.

Углубляться в настройки логов не будем, потому просто приведу пример:

logging {
       channel b_log {
                file "/var/log/named/named.log" versions 30 size 1m;
                print-time yes;
                print-category yes;
                print-severity yes;
                severity info;
        };

        channel b_debug {
                file "/var/log/named/debug.log" versions 2 size 1m;
                print-time yes;
                print-category yes;
                print-severity yes;
                severity dynamic;
        };

        channel b_query {
                file "/var/log/named/query.log" versions 2 size 1m;
                print-time yes;
                severity info;
        };

        channel default_syslog {
                syslog daemon;
                severity info;
        };

        category default { b_log; b_debug; };
        category config { b_log; b_debug; };
        category queries { b_query; default_syslog; };
};

Список доступа в котором определены виртуальные сети:

acl "vlan100" { 192.168.0.0/22; };

С помощью view можно задавать разные конфигурации для разных виртуальных сетей используя списки доступа:

view "vlan100" {
        match-clients { vlan100; };
        allow-query { vlan100; };
        allow-query-cache { vlan100; };
        allow-recursion { vlan100; };
        allow-transfer { 192.168.0.9; };
        zone "myblog.ru" IN {
                type master;
                file "/etc/named/named.0x.myblog.zones";
        };
        zone "0.168.192.in-addr.arpa" IN {
                type master;
                file "/etc/named/0.168.192.in-addr.arpa";
        };
};

match-clients — разрешает запрос только с указанных в acl «vlan100» сетей.
allow-transfer — разрешает передавать данные указанному в директиве DNS серверу.
zone — указывает расположение файлов зон прямой и обратной видимости т.е. в зону прямой видимости будем записывать все DNS записи, а DNS запись типа PTR будем записывать в зону обратной видимости (in-addr.arpa).

Пример зоны обратной видимости

Создаем файл 0.168.192.in-addr.arpa и приводим его к следующему виду:

$TTL 14400
@       IN      SOA     myblog.ru root.myblog.ru (
                        0211181503      ; serial
                        10800           ; refresh
                        3600            ; retry
                        604800          ; expire
                        38400 )         ; minimum
$ORIGIN 0.168.192.in-addr.arpa.
@                               IN      NS      myblog.ru.
4.0.168.192                     IN      PTR     www.myblog.ru.
6.0.168.192                     IN      PTR     jira.myblog.ru.

TTL — время жизни записи по истечении которого происходит обновление информации.
$ORIGIN — обычно здесь указывается доменный адрес самого DNS сервера, но в случае с обратной зоной надо указывать файл, в котором и прописаны данные.
@ — обозначает сам сервер т.е. в этом случае сам сервер является DNS сервером обслуживающим зону myblog.ru.
PTR — в нем указан IP адрес сервера на котором хостится сайт www.myblog.ru, но записан в обратном порядке октетов.

Пример зоны прямой видимости

Создадим файл named.0x.myblog.zone:

$TTL 14400
@       IN      SOA     myblog.ru root.myblog.ru (
                        1427170619      ; serial
                        10800           ; refresh
                        3600            ; retry
                        604800          ; expire
                        38400 )         ; minimum
@                       IN      NS      myblog.ru.
myblog.ru.              IN      A       x.x.x.x
www                     IN      CNAME   myblog.ru.
jira                    IN      A       192.168.0.6

Как видно в примере www является alias’ом записи типа A. Обратите внимание, что при указании CNAME надо в конце ставить точку. Вообще точка в DNS является своего рода символом терминирования значения. Например, если с компа подключенного к контроллеру домена или имеющего DNS суффикс набрать nslookup www, то после www автоматически допишется суффикс .myblog.ru, а значит если наберете nslookup www.myblog.ru, то будет попытка отрезолвить адрес www.myblog.ru.myblog.ru. Потому в конце надо ставить точку (nslookup www.myblog.ru.) или просто резолвить указанием коротких имен.
Стоит запомнить, что если вносите изменения в файл зоны, то необходимо менять значение serial, чтобы корректно обновился кэш у клиентов DNS. Для этого можно использовать формат даты. Например, 1427170619 можно интерпретировать как 14 часов 27 минут, 17-ое число, 06-ой месяц, 19-ый год т.е. все вместе будет 1427170619. Таким образом число serial не будет повторятся и всегда можно будет прочесть, когда обновлялся файл зоны.

Перенаправление запросов к контроллеру домена

Также можно настроить Bind таким образом, чтобы все запросы на подключение к Active Directory пересылались на Windows Server:

;active directory
dc.myblog.ru.                  IN      A       192.168.0.9
winserv.dc.myblog.ru.          IN      A       192.168.0.9
gc._msdcs.dc.myblog.ru.        IN      A       192.168.0.9
_gc._tcp.dc.myblog.ru.                                 IN      SRV     0       100     3268    winserv.dc.myblog.ru.
_gc._tcp.Default-First-Site-Name._sites.dc.myblog.ru.  IN      SRV     0       100     3268    winserv.dc.myblog.ru.
_ldap._tcp.dc.myblog.ru.                               IN      SRV     0       0       389     winserv.dc.myblog.ru.
_kerberos._tcp.dc.myblog.ru.                           IN      SRV     0       0       88      winserv.dc.myblog.ru.
_ldap._tcp.dc._msdcs.MYBLOG.                           IN      SRV     0       0       389     winserv.dc.myblog.ru.
_kerberos._tcp.dc._msdcs.MYBLOG.                       IN      SRV     0       0       88      winserv.dc.myblog.ru.
_ldap._tcp.dc._msdcs.dc.myblog.ru.                     IN      SRV     0       0       389     winserv.dc.myblog.ru.
_kerberos._tcp.dc._msdcs.dc.myblog.ru.                 IN      SRV     0       0       88      winserv.dc.myblog.ru.

Теперь если прописать в качестве первичного DNS сервера адрес Bind, то при подключении компа к контроллеру домена комп успешно подключится. В некоторых случаях такой подход вполне оправдан особенно учитывая, что майрософтский DNS сервер не поддерживает views.