13. Основы DNS ч.2
Вступление
В прошлый раз мы с вами разобрали, что такое домен, что такое зона, делегирование, SOA, NS записи и некоторые другие основы DNS. Предлагаю не тратить время на очередную теорию про другие основные типы DNS записей, этого в интернете и так полно, мы же их будем рассматривать по мере практической необходимости. К примеру, будем разбирать почтовый сервер - зайдём на DNS сервер, пропишем необходимые типы записей для почтового сервера, там же их и разберём.
А пока, давайте поднимем DNS сервер. Есть разные реализации, мы будем учиться на bind. Это сервер от той же организации, которая разрабатывает dhcp сервер, разбираемый в предыдущих темах. Почему именно bind? С одной стороны он известный, много где применяется, а с другой - это хороший пример для обучения работы с сервисами в командой строке Linux. Если раньше в отношении сервисов мы просто редактировали конфиг файл и рестартовали сервис, то с bind всё чуть комплекснее - помимо настроек самого демона, у него есть ещё файлы зон и утилиты, которые управляют DNS сервером.
Подготовка виртуальной машины
Начнём с того, что добавим ещё одну виртуалку в нашу схему, назовём её ns1 и подключим в серверный влан используя оба свитча. Настройку тиминга и выдачу хостнейма сделайте сами.
DNS сервер, в некотором роде, будет связывать все системы внутри нашей инфраструктуры. И если вдруг у него поменяется IP адрес - это может привести к плохим последствиям. Поэтому давайте зарезервируем IP адрес на dhcp сервере.
Заходим на dhcp сервер и смотрим список выданных адресов:
perl /usr/share/doc/dhcp-server/dhcp-lease-list.pl
В табличке с помощью колонки hostname находим наш сервер ns1 и копируем его мак адрес.
Дальше заходим в конфиг с резервациями нашего dhcp сервера и добавляем новую запись.
/etc/dhcp/dhcpd.conf.d/reservation.conf
host ns1 {
hardware ethernet 0c:35:c4:37:00:00;
fixed-address 10.0.4.53;
}
Я дал адрес 53, так как DNS работает на 53 порту. Так будет легче запомнить, что за этим адресом DNS сервер.
Не забываем после изменений скопировать конфиг файл с резервациями на второй dhcp сервер, а дальше перезапускаем сервис dhcpd:
systemctl restart dhcpd
Чтобы наш новый сервер получил новый адрес, переподключаем на нём сетевой интерфейс и проверяем IP адрес.
nmcli con up team
ip a show team0
Правим ssh конфиг и подключаемся к новому DNS серверу:
ssh ns1
Установка bind
Установим bind:
sudo yum install bind -y
Тут с названиями довольно запутано - пакет называется bind, его сервис в systemd называется named, а в файроволе сервис называется просто dns.
Так как мы в тестовой среде, можем сразу запустить сервис и добавить его на файрвол:
sudo systemctl enable --now named
sudo firewall-cmd --add-service=dns --permanent
sudo firewall-cmd --reload
Но в реальной среде так делать не стоит, лучше предварительно настроить, а уже потом запускать сервис и добавлять его на файрволе. Если вы будете разворачивать сервис в интернете, то может сложиться ситуация, что у какого-то демона, по-умолчанию, не безопасные настройки. И пока вы будете с ними возиться, кто-то уже успеет сделать что-то плохое.
Разбор настроек
Основной файл настроек bind-а - /etc/named.conf. Тут у нас всё что касается самого демона - на каких портах он работает, всякие настройки кэширования, безопасности и прочее. Ещё здесь указываются зоны, но всё что касается самих DNS записей прописывается в других файлах, до них мы ещё дойдём. Пока разберём этот файл.
Сверху мы видим небольшую подсказку. Она может привести нас к примерам, где можно найти чуть более детальные конфиги:
ls /usr/share/doc/bind*/sample/
ls /usr/share/doc/bind*/sample/etc
cat /usr/share/doc/bind*/sample/etc/named.conf
Да, всё это можно найти и в интернете, но иногда, если что-то вылетело из головы, легче взглянуть на пример и вспомнить, чем пытаться это нагуглить. Ну и взглянув на готовые примеры можно встретить то, что и не думал искать раньше. К примеру, пока я не взглянул на этот конфиг, я и не думал, что у bind есть графическая утилита для настройки.
Сам конфиг напоминает конфиг для DHCP сервера - также используются точки с запятыми как разделители, комментарии со слешами и звёздочками, секции с фигурными скобками, также есть возможность расширить настройки на несколько файлов с помощью include. Основные настройки самого демона находятся в секции options, есть отдельная секция logging, есть секции под специфичные нужды, такие как view, key, trusted-keys, zone. Всё это мы будем разбирать по мере необходимости.
Вернёмся к основному конфигу и пройдёмся по секции options:
sudo nano /etc/named.conf
listen-on
- указывает, на каких адресах и портах работает этот демон. DNS по умолчанию работает на 53 порту, и вы, скорее всего, никогда не поменяете стандартный порт. Большинство DNS клиентов даже не позволяют указать другой порт. То есть, если вы настроите здесь не стандартный порт - то ваши клиенты просто не смогут достучаться до DNS сервера. Да, есть DNS-over-TLS или DNS-over-HTTPS, они используют не 53 порт, но это настраивается по другому и не связано с этим параметром. Разве что DNS сервера могут обращаться друг к другу по нестандартным портам, и это может быть полезно в каких-то специфичных случаях.В фигурных скобках мы видим 127.0.0.1. Это означает, что этот DNS сервер слушает только на этом адресе, а значит он доступен только сам для себя. Чтобы другие компьютеры могли к нему обращаться, давайте добавим сюда также его основной адрес. И не забудьте поставить точку с запятой после:
listen-on port 53 { 127.0.0.1; 10.0.4.53; };
listen-on-v6
- тоже самое, что и listen-on, но предназначенное для ipv6.
Дальше идут несколько параметров, которые полезно понимать, но зачастую нет смысла трогать:
directory
- основная директория с файлами. Здесь обычно всякие файлы с DNS записями, временные файлы и прочее. Мы ещё сюда зайдём.dump-file
- Файл, куда сохраняется кэш во время работы DNS сервера. Огромная часть работы DNS сервера - работа с кэшем, чтоб не узнавать ответ на каждый запрос повторно, что занимает гораздо больше времени и ресурсов. Если у вас есть высоконагруженный DNS сервер, на него приходит огромное количество DNS запросов, и вдруг сервис падает, даже если он моментально заново поднимется, восстановление кэша с нуля может быть лишней тратой времени и ресурсов. А при наличии такого dump-файла процесс восстановления будет гораздо быстрее.statistics-file
- файл, куда сливается статистика с работы сервиса - количество и типы DNS запросов, сколько заняли времени и т.п.memstatistics-file
- ещё один файл статистики, но больше связанный с потреблением памяти.secroots-file
- файл, куда кэшируются ключи для проверки подписей для DNSSEC. DNSSEC это отдельная тема, которую я не хочу пока мешать с основами DNS, её мы разберём отдельно.recursing-file
- файл, куда будет записан вывод командыrndc recursing
, который покажет текущие рекурсивные запросы. Может пригодится при поиске проблем с рекурсивными запросами.
Теперь перейдём к параметрам поинтереснее:
allow-query
- разрешить запросы - и в скобках мы указываем откуда.listen-on
просто позволяет сервису слушать на указанных адресах, но это не значит, что он будет отвечать всем, кто пришёл на этот адрес. В нашем случае, сейчас:allow-query { localhost; };
настроено так, что сервер будет отвечать только на свои запросы, а на все запросы с других IP адресов он будет отвечать отказом. В скобках мы можем указать конкретные IP адреса, подсети или просто
any
, чтобы отвечать всем.Так как мы поднимаем сервис для нашей локальной сети, давайте укажем
10.0.0.0/8
:allow-query { localhost; 10.0.0.0/8; };
И ещё раз напомню - не забывайте ставить точку с запятой в конце.
Обратите внимание, что нигде в этом конфиг файле нет какого-то комментария с объяснением параметра кроме одного специфичного места:
recursion
- позволяет сделать DNS сервер рекурсивным или отрубить этот функционал. Рекурсивный DNS сервер - это такой DNS сервер, который, получая запрос от клиента, ищет у себя в кэше, и если не найдёт - он идёт на другой DNS сервер, чтобы узнать ответ там. Узнав ответ, он отвечает клиенту и сохраняет ответ у себя в кэше, на случай, если будут ещё такие запросы.То есть задача рекурсивного DNS сервера - находиться поближе к клиентам и быстро отвечать на запросы, чтобы ускорить работу с DNS и не гонять трафик просто так. Поэтому его также называют кэширующим DNS сервером.
Если есть DNS сервера, которые перенаправляют запросы, значит есть и сервера, которые предоставляют ответы - авторитетные DNS сервера. Задача таких DNS серверов - предоставлять информацию о зонах. К примеру, если у вас есть домен и вы хотите для него создать DNS записи, то вам нужен авторитетный DNS сервер.
Скажем, DNS на вашем домашнем дешёвом роутере может быть только кэширующим. Если вы поднимаете DNS сервер в интернете, чтобы делиться информацией о вашем домене, то не стоит его делать рекурсивным, иначе с помощью вашего сервера будут делать DDOS атаки. Об этом и предупреждают в комментарии в этом конфиге.
Но не то чтобы авторитетный и рекурсивный сервера были взаимоисключающими. Например, немало компаний используют Microsoft Active Directory, где встроена служба DNS, которая одновременно и рекурсивная, и авторитетная. Да, к DNS сервису Active Directory из интернета доступ давать не стоит, но вот внутри сети компании можно пользоваться.
В этой теме мы сделаем кэширующий DNS сервер, поэтому оставляем этот параметр со значением
yes
.
И так, мы решили, что наш DNS сервер будет рекурсивным. А рекурсивный должен узнавать ответы от других серверов. А из каких? Правильно, нам нужен параметр:
forwarders
- указывает, к каким DNS серверам нужно обращаться за ответами. Здесь вы можете указать DNS адреса провайдеров, так как они обычно ближе по сети, или какие-либо другие более доверенные сервера. Тут уже на ваше усмотрение. По личному опыту, я встречал несколько раз ситуации, когда у провайдеров возникают проблемы с DNS серверами и от этого страдает сеть компании. Но на вопрос «кому доверять DNS запросы компании в интернете» нет простого ответа, и, для примера, я просто указал сервера Cloudflare и Google.forwarders { 1.1.1.1; 8.8.8.8; };
Дальше идёт несколько параметров, связанных с DNSSEC, но мы это разберём в отдельной теме, поэтому сейчас их пропустим.
Перейдём к секции logging. bind делит логи на различные категории.
Категории могут быть связаны с клиентскими запросами, конфиг файлами, dnssec и прочим.
Эти категории можно направить в различные каналы.
Вы создаёте каналы, где указываете, что делать с логом - записать в файл, отправить в syslog, добавить ли время лога, или может в целом ничего не делать с этим логом.
И в секции logging вы указываете, какую категорию в какие каналы стоит направлять:
logging {
category default { default_logfile; default_debug; };
category unmatched { null; };
};
Дальше у нас секция про корневую зону «.».
Давайте посмотрим на содержимое указанного файла named.ca
:
sudo cat /var/named/named.ca
Здесь мы видим адреса корневых DNS серверов.
Помните, мы говорили, что DNS адрес как путь в Linux, только читается наоборот и вместо slash - точка? Благодаря этому файлу наш DNS сервер знает об адресах корневых DNS серверов. Если бы мы оставили параметр recursion yes
, при этом не добавив forwarders
, то наш DNS сервер сначала бы посылал запрос на эти корневые сервера, чтобы узнать DNS сервера для доменов первого уровня, затем обращался к тем, чтобы найти адреса DNS серверов для доменов второго уровня и дальше в зависимости от необходимой зоны. В прошлой теме мы с nslookup проходились по всей этой цепочке, поэтому советую предварительно посмотреть предыдущую тему.
Так вот, если бы за каждым запросом мы бы ходили через такую огромную цепочку, то всё работало бы в разы медленнее, не говоря уже о том, что нагрузка на все эти сервера была бы безумной. Вот почему важно указывать forwarders.
И в конце у нас два include:
include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";
Давайте посмотрим что в них.
sudo cat /etc/named.rfc1912.zones
Первый файл содержит специфичные зоны, связанные с localhost.
А второй файл, опять же, связан с DNSSEC.
Запуск сервиса
И так, давайте сохраним файл. Так как мы поменяли пару настроек, не забудем перезапустить named для применения наших изменений:
sudo systemctl restart named
Мы сделали restart, так как пока что нашим DNS сервером никто не пользуется и перезагрузка сервиса не страшна. Но в будущем, когда нужно будет применить настройки на рабочем DNS сервисе, которым уже пользуются клиенты, так делать не стоит, потому что это приведёт к недоступности DNS сервера, а это может привести к серьезным последствиям.
Для безболезненного применения настроек можем использовать reload вместо restart:
sudo systemctl cat named | grep Reload
Как видите, reload задействует утилиту rndc - с помощью неё можно управлять bind, при чем не только локальным.
Если вы где-то опечатались, а очень часто новички забывают где-то точку с запятой и сервис потом не стартует, то легче всего посмотреть в логи, где можно будет найти номер строки с ошибкой:
sudo journalctl -eu named
В моих логах я вижу другую ошибку - host unreachable resolving, timeout и прочее. Это говорит о том, что у моего DNS сервера нет доступа к указанным DNS серверам.
Настройка firewall
Давайте попытаемся разобраться. Пустим ping на 1.1.1.1, чтобы понять, есть ли сетевой доступ:
ping 1.1.1.1
Да, единички пингуются, значит у этой системы есть доступ в интернет.
Однако, если мы попытаемся пингануть google.com
то увидим ошибку Name or service not known
:
ping google.com
Это нам говорит о том, что не резолвятся имена.
Давайте проверим resolv.conf:
cat /etc/resolv.conf
И здесь мы видим, что у нас прописаны эти самые единички, и они у нас пингуются. И так, пинг у нас доходит, но DNS запросы нет. Почему?
Самое время вспомнить, что у нас сервера существуют не в вакууме, а в нашей сети. И в нашей сети есть файрволы, которые не пускают ничего, кроме пингов. Значит нам надо разрешить нашим DNS серверам доступ в интернет, хотя бы для сервиса DNS.
Идём на router3 и смотрим все политики:
sudo firewall-cmd --list-all-policies
И обнаружимваем, что оказывается, мы уже разрешали нашим серверам доступ в интернет, в том числе по DNS.
Однако, если зайти на router4, можем заметить, что такой политики нет.
sudo firewall-cmd --list-all-policies
Мы забыли её добавить. Ладно, не страшно, быстренько вспоминаем:
Просто скопируем из второй темы по DHCP команды для создания политики, добавления в неё зон, добавление сервисов и, собственно, рестарт firewall.
sudo firewall-cmd --permanent --new-policy=srv_to_internet
sudo firewall-cmd --permanent --policy=srv_to_internet --add-ingress-zone=servers
sudo firewall-cmd --permanent --policy=srv_to_internet --add-egress-zone=routers
sudo firewall-cmd --permanent --policy=srv_to_internet --add-service={dns,http,https}
sudo firewall-cmd --reload
Возвращаемся на ns1 и проверяем пинг:
ping google.com
Теперь всё пингуется и резолвится. Но, обратите внимание, пинг идёт не благодаря нашему новому DNS сервису, в /etc/resolv.conf были прописаны единички. То есть мы пока что не тестировали наш DNS сервер.
То что мы подняли DNS сервер не значит, что все компьютеры в нашей сети автоматом стали его использовать. Они даже его не знают. А как они могут узнать, что у нас в сети есть DNS сервер? Правильно, DHCP! Это DHCP сервер говорит всем нашим компьютерам адреса DNS серверов.
Пойдём на DHCP сервера и прежде всего проверим, могут ли они использовать наш DNS сервер. Как проверить, работает ли DNS сервер? Правильно, к примеру с помощью nslookup с указанием сервера:
nslookup google.com 10.0.4.53
Мы видим, что есть ответ. Значит что? Значит наш DNS работает. Но наш DHCP сервер находится в той же подсети, что и DNS сервер, а это значит, что мы не учитываем firewall.
Попробуем тоже самое с пользовательского компьютера.
nslookup google.com 10.0.4.53
И на этот раз мы видим connection timed out
. Как мы и предполагали, все кто находится в серверной сети могут достучаться до DNS, а вот для остальных стоит прописать политику на наших файрволах.
Идём на router3. Добавим политику, назовём её просто - dns:
sudo firewall-cmd --new-policy=dns --permanent
Для этой политики входящей зоной будет любая - ANY, а исходящей - сервера:
sudo firewall-cmd --policy=dns --add-ingress-zone=ANY --permanent
sudo firewall-cmd --policy=dns --add-egress-zone=servers --permanent
Мы не хотим, чтобы любой пользователь мог подключиться к любому серверу по DNS, а только к одному определённому. Поэтому добавляем rich-rule:
sudo firewall-cmd --policy=dns --permanent --add-rich-rule='rule family=ipv4 source address=10.0.0.0/8 destination address=10.0.4.53/32 port port=53 protocol=udp accept'
Не забываем перезапустить файрвол:
sudo firewall-cmd --reload
Ну и самое главное, на этот раз, не забудем добавить тоже самое на втором файрволе. Будь у нас какой-нибудь коммерческий firewall, он бы в режиме репликации копировал настройки на оба наших файрвола, но вряд ли firewalld рассчитан на такое применение. Но я в своих темах показываю идею, что и для чего делать, и в данном случае: поднял сервис - надо добавить на файрволе.
Вернёмся и проверим снова - и теперь мы видим, что user1 получает ответ от DNS сервера.
Настройка DHCP
Отлично, значит мы можем обновить настройки на DHCP серверах.
Идём на dhcp1, заходим в настройки подсетей:
sudo nano /etc/dhcp/dhcpd.conf.d/subnets.conf
Раньше в параметре domain-name-servers
у нас было два DNS сервера, но мы пока что подняли только один, так что укажем только его:
option domain-name-servers 10.0.4.53;
Сохраняем изменения, выходим и перезапускаем сервис для применения настроек.
Проделываем ту же операцию на втором DHCP сервере.
Мы могли бы дождаться, пока dhcp клиенты свяжутся с сервером по поводу обновления lease time и получат новые настройки, но это может занять время. И чтобы ускорить этот процесс, я просто переподключусь к сети на пользовательском компьютере:
nmcli con up ens3
Проверю /etc/resolv.conf
:
cat /etc/resolv.conf
И здесь мы видим, что адрес DNS сервера обновился. Можем для проверки ещё раз пустить nslookup:
nslookup 10.0.4.53
И всё работает.
Итоги
По хорошему, нам теперь надо вернуться на файрвол, убрать доступ к DNS в интернете всем серверам и прописать специфичное правило - чтобы только ns1 мог подключаться в интернет только к своим forwarders. Но это будет заданием для вас.
Ну и другое задание - поднять ns2. Поднять второй кэширующий DNS сервер будет довольно просто - нужно поднять точно такой же сервис, точно с такими же настройками, добавить его на файрволе и в DHCP. Сервера между собой никак не связаны, не делятся никакими пулами, как тот же DHCP, не нужно разделять один и тот же IP адрес. Все DNS клиенты поддерживают несколько DNS серверов, благодаря чему можно прописав на клиентах два DNS адреса сделать отказоустойчивость.
И так, подытожим. Мы сегодня поставили bind, прошлись по настройкам и настроили его как кэширующий DNS сервер. При этом интегрировали его в нашу сеть - обновили правила на файрволах, обновили настройки DHCP серверов и проверили работоспособность. В будущих темах мы разберём, как поднять авторитетный DNS сервер, поговорим про DNSSEC, DNS-over-TLS и прочее.