Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Кэш DNS на уровне узла

Оригинал: Localhost DNS Cache
Автор: Kyle Rankin
Дата публикации: 23 февраля 2015 г.
Перевод: А.Панин
Дата перевода: 3 августа 2015 г.

Кэш DNS на уровне узла

Покажется ли вам странным мое признание в том, что DNS является моим любимым протоколом? Но ведь DNS действительно является моим любимым протоколом. Меня привлекают простота пакетов UDP и мощь сервиса, который позволяет корректно функционировать всей сети Интернет. В течение многих лет я был впечатлен тем, насколько малый объем свободных ресурсов требуется для ввода в эксплуатацию инфраструктуры DNS внутренней сети.

Не так давно в процессе развития одного из моих вычислительных окружений я обнаружил, что несмотря на корректную работу серверов DNS под постоянно возрастающей нагрузкой в журналах запросов достаточно много повторяющихся с частотой в несколько секунд записей, соответствующих запросам разрешения имен одних и тех же узлов. Очевидно, что обычно в процессе стандартной установки системы Linux не выполняется установка какого-либо программного продукта для локального кэширования запросов DNS. Это означает, что каждый раз при необходимости преобразования имени узла в IP-адрес осуществляется отправка запроса к внешнему серверу DNS вне зависимости от установленного времени жизни соответствующей ресурсной записи (TTL).

В данной статье рассказывается о том, насколько прост процесс установки легковесного кэширующего сервера DNS, который не делает ничего, кроме передачи запросов DNS установленным ранее серверам имен и кэширования возвращаемых ими результатов с учетом времени жизни ресурсных записей (TTL).

Существует множество различных способов реализации кэширования запросов DNS. В прошлом я использовал такие системы, как nscd, которые перехватывали запросы DNS до того момента, когда они отправлялись серверам имен, адреса которых приведены в файле конфигурации /etc/resolv.conf, и устанавливали, присутствуют ли эти запросы в кэше. Несмотря на то, что данный подход был работоспособным, я всегда считал, что в случае неполадок диагностика системы nscd гораздо сложнее диагностики обычного сервера DNS. Мне хотелось настроить обычный локальный сервер DNS, который мог бы учитывать время жизни ресурсных записей (TTL), но перенаправлял бы все запросы моим реальным серверам имен. Таким образом можно было добиться повышения скорости разрешения доменных имен и снижения нагрузки на сервер благодаря локальному кэшу DNS и в то же время иметь возможность диагностики любых ошибок с помощью стандартных инструментов, предназначенных для диагностики серверов DNS.

Найденным мной решением являлся сервер dnsmasq. Вообще, я не большой сторонник dnsmasq из-за того, что данный программный продукт обычно позиционируется как легко настраиваемое полноценное серверное решение, поддерживающее как протокол DNS, так и протокол DHCP, а я предпочитаю использовать отдельные службы для работы с каждым из протоколов. Конфигурация dnsmasq обычно предусматривает чтение списка адресов внешних серверов имен из файла конфигурации /etc/resolv.conf с использованием файла конфигурации /etc/hosts для настройки зоны DNS. Я хотел использовать абсолютно другой подход. Но в моем распоряжении уже имелись полнофункциональные серверы DNS, а в том случае, если бы я захотел использовать для разрешения доменных имен файл конфигурации /etc/hosts вместо протокола DNS, я мог бы сесть в свой DeLorean и умчаться в начало 80-х годов. Исходя из этого, часть моего файла конфигурации dnsmasq будет содержать директивы отключения множества используемых по умолчанию возможностей.

На первом шаге следует установить dnsmasq. Данный программный компонент доступен из репозиториев большинства дистрибутивов, поэтому используйте стандартный менеджер пакетов программного обеспечения для установки пакета с именем dnsmasq. В моем случае пакет программного обеспечения устанавливается в дистрибутиве Debian, поэтому в файле конфигурации будут встречаться некоторые специфичные для данного дистрибутива директивы, о которых следует помнить в случае работы с другим дистрибутивом. В первую очередь следует обратить внимание на то, что некоторые очень важные параметры конфигурации размещены в файле /etc/default/dnsmasq. Данный файл содержит подробные комментарии, поэтому я не буду приводить его содержимое в рамках данной главы. Вместо этого я приведу значения двух переменных, которые должны быть установлены в рамках данного файла.

ENABLED=1
IGNORE_RESOLVCONF=yes

Первая переменная позволяет осуществлять запуск службы, а вторая позволяет передать dnsmsq информацию о том, что следует игнорировать всю информацию от службы resolvconf (если она установлена) при установлении адресов серверов имен, которые будут использоваться. В любом случае я буду задавать их адреса вручную.

На следующем шаге необходимо настроить сам сервер dnsmasq. Стандартный файл конфигурации данного сервера расположен по пути /etc/dnsmasq.conf и вы можете редактировать его непосредственно при необходимости, но в моем случае в дистрибутиве Debian создается директория /etc/dnsmasq.d, в которой могут располагаться файлы конфигурации, из которых загружаются параметры конфигурации. Являясь постоянным пользователем различных систем конфигурации приложений, я предпочитаю модель конфигурации на основе директории конфигурационных файлов <имя_сервиса>.d, так как она упрощает передачу приложению различных параметров конфигурации для различных условий использования этого приложения. В том случае, если в вашем дистрибутиве не осуществляется автоматическое создание описанной директории, вы можете либо непосредственно редактировать файл конфигурации /etc/dnsmasq.conf, либо добавить в данный файл конфигурации с именем dnsmasq.conf аналогичную директиву:

conf-dir=/etc/dnsmasq.d

Мне пришлось создать новый файл конфигурации по пути /etc/dnsmasq.d/dnscache.conf со следующими директивами:

no-hosts
no-resolv
listen-address=127.0.0.1
bind-interfaces
server=/dev.example.com/10.0.0.5
server=/10.in-addr.arpa/10.0.0.5
server=/dev.example.com/10.0.0.6
server=/10.in-addr.arpa/10.0.0.6
server=/dev.example.com/10.0.0.7
server=/10.in-addr.arpa/10.0.0.7

Давайте рассмотрим каждую из директив. Первая директива, no-hosts, сообщает dnsmasq о том, что следует игнорировать файл конфигурации /etc/hosts и не использовать его в качестве источника ресурсных записей DNS. В данном случае dnsmasq будет использовать лишь внешние серверы имен. Директива no-resolv сообщает dnsmasq о том, что не следует использовать конфигурационный файл /etc/resolv.conf для получения списка адресов внешних серверов имен. Эта директива важна из-за того, что впоследствии в файл конфигурации /etc/resolv.conf будет добавлен IP-адрес системы, на которой установлен сервер dnsmasq, что может привести к появлению своего рода циклических ссылок. Две следующие директивы, listen-address и bind-interfaces, позволяют быть уверенным в том, что dnsmasq резервирует сетевой порт и принимает соединения лишь от клиентов с локального узла (с IP-адресом 127.0.0.1). Вы можете использовать данные директивы для того, чтобы избежать использования вашего сервера в качестве открытого DNS-релея клиентами из внешних сетей.

С помощью директив server задаются адреса внешних серверов DNS, которые будут использоваться dnsmasq. Я добавил в файл конфигурации адреса трех различных внешних серверов имен в предпочтительном порядке. Синтаксис данной строки: server=/используемый_домен/ip_адрес_сервера_имен. Таким образом, в примере выше сервера имен будут использоваться для разрешения имен в рамках домена dev.example.com. Я также хотел бы использовать данные серверы имен для преобразования IP-адресов в имена доменов (на основе ресурсных записей PTR), поэтому ввиду того, что все внутренние IP-адреса находятся в рамках сети 10.x.x.x, я добавил строку 10.in-addr.arpa в качестве имени используемого домена.

После сохранения изменений в файле конфигурации следует перезапустить службу dnsmasq для применения новых параметров конфигурации. Теперь вы можете использовать утилиту dig по отношению к локальному узлу для тестирования работоспособности сервера dnsmasq:

$ dig ns1.dev.example.com @localhost

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> ns1.dev.example.com @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4208
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;ns1.dev.example.com.                   IN      A

;; ANSWER SECTION:
ns1.dev.example.com.    265     IN      A       10.0.0.5

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu Sep 18 00:59:18 2014
;; MSG SIZE  rcvd: 56

В приведенном выше примере я попытался протестировать работоспособность локального сервера DNS, обратившись к узлу с именем ns1.dev.example.com, и получил IP-адрес узла 10.0.0.5. Если вы внимательно рассмотрите вывод утилиты dig, вы можете обнаружить в конце строку SERVER: 127.0.0.1#53(127.0.0.1), которая указывает на то, что я на самом деле получил ответ от сервера на локальном узле с IP-адресом 127.0.0.1. Если вы снова выполните данную команду через короткий промежуток времени, вы можете обнаружить, что присутствующее в выводе значение времени жизни ресурсной записи TTL (в примере выше оно было равно 265) уменьшится. Сервер dnsmasq кэширует ответ сервера DNS и, после того, как значение времени жизни ресурсной записи TTL становится равным нулю, снова отправляет запрос удаленному серверу.

После того, как вы убедитесь в работоспособности сервера dnsmasq, на последнем шаге вам придется модифицировать файл конфигурации /etc/resolv.conf таким образом, чтобы строка с указанием адреса локального сервера имен nameserver 127.0.0.1 располагалась над всеми остальными строками с указаниями адресов удаленных серверов имен. Учтите, что вы можете оставить в файле все существующие адреса удаленных серверов имен. Фактически, данный подход является даже более безопасным, ведь он позволяет использовать удаленные серверы DNS даже в случае краха сервера dnsmasq. Если же вы используете сервер DHCP для получения IP-адреса машины или получаете данную информацию из какого-либо файла (таким образом, как в случае установки службы resolvconf), вам придется самостоятельно разобраться с тем, какой файл следует модифицировать; в противном случае при следующем получении данных от сервера DHCP содержимое рассматриваемого файла конфигурации будет перезаписано.

Я внес описанные простые изменения в конфигурацию около 100 серверов из отдельного рабочего окружения и был удивлен кардинальным снижением трафика DNS, нагрузки и количества записей в файлах журналов моих внутренних серверов имен. Более того, данная конфигурация является менее восприимчивой к сбоям, ведь в случае реальных проблем с внешними серверами DNS кэшированные ресурсные записи будут предаваться клиентам до момента истечения их времени жизни TTL. Таким образом, в том случае, если вы обнаружите, что ваши внутренние серверы имен обрабатывают чрезмерный объем трафика, использование внутренних кэширующих серверов DNS является первым решением, которое определенно следует рассмотреть.