Каждый раз, когда серверу нужно узнать доменное имя, он отправляет DNS-запрос другому резолверу. Даже если одни и те же домены запрашиваются постоянно, повторные запросы все равно проходят через сеть, хотя ответ скорее всего не изменился.

Представьте веб-приложение, которое при каждом посещении сайта обращается к трём внешним API. Если сервер обрабатывает тысячи запросов в день, он столько же раз выполняет одни и те же DNS-запросы.

Это лишний сетевой трафик и небольшая задержка при каждом запросе. Локальный кеширующий DNS-резолвер решает проблему: он сохраняет недавно использованные DNS-записи и повторно применяет их до истечения срока действия. На Rocky Linux 10 настроить такой резолвер с помощью Unbound можно примерно за десять минут.

Unbound — это легковесный проверяющий рекурсивный DNS-резолвер, разработанный NLnet Labs. В отличие от BIND или PowerDNS, он не предназначен для размещения DNS-зон. Его основная задача — разрешать DNS-запросы, кешировать результаты в памяти и мгновенно возвращать закешированные ответы при повторном запросе того же домена.

Шаги, описанные в этом руководстве, одинаково работают на Rocky Linux 10, RHEL 10 и AlmaLinux 10. Все три дистрибутива предоставляют один и тот же пакет unbound через dnf, используют одни и те же файлы конфигурации и ведут себя практически идентично после установки и запуска службы.

Лабораторное окружение

Для этого руководства мы будем использовать две системы Rocky Linux 10.

  • DNS-сервер: 192.168.1.50 (resolver.rootpathlocal.com).

  • Клиент: 192.168.1.75 (app01.rootpathlocal.com).

На DNS-сервере будет запущен Unbound, а клиент станет использовать его для DNS-запросов.

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

Выполните на DNS-сервере следующие команды, чтобы проверить имя хоста и IP-адрес:

hostnamectl
ip -4 addr show

Вы должны увидеть, что имя хоста сервера задано как resolver.rootpathlocal.ru, а сетевому интерфейсу присвоен IP-адрес 192.168.1.50. Если в вашей среде используются другие значения, просто заменяйте имена хостов и IP-адреса в этом руководстве на свои собственные.

Шаг 1: Установка Unbound

Начните с обновления системных пакетов, затем установите Unbound вместе с пакетом bind-utils.

sudo dnf update -y
sudo dnf install -y unbound bind-utils

Пакет bind-utils включает команду dig, один из самых полезных инструментов для тестирования DNS. Мы воспользуемся ей позже, чтобы убедиться, что Unbound корректно разрешает запросы и отдаёт закешированные результаты.

Перед внесением любых изменений разумно создать резервную копию стандартного файла конфигурации Unbound. Если вы случайно допустите ошибку при редактировании, можно быстро восстановить исходный файл, не переустанавливая пакет.

sudo cp /etc/unbound/unbound.conf /etc/unbound/unbound.conf.orig

Шаг 2: Настройка Unbound

Откройте файл конфигурации Unbound в предпочитаемом текстовом редакторе.

sudo vi /etc/unbound/unbound.conf

Внутри секции server: добавьте или обновите следующие параметры:

server:
    interface: 192.168.1.50
    interface: 127.0.0.1
    port: 53

    do-ip4: yes
    do-udp: yes
    do-tcp: yes

    access-control: 127.0.0.0/8 allow
    access-control: 192.168.1.0/24 allow
    access-control: 0.0.0.0/0 refuse

    hide-identity: yes
    hide-version: yes

    verbosity: 1
    logfile: "/var/log/unbound.log"
    use-syslog: no

Назначение этих параметров:

  • interface указывает IP-адреса, на которых Unbound ожидает DNS-запросы. В этом примере он слушает LAN-адрес сервера (192.168.1.50) и локальный loopback-адрес (127.0.0.1), что позволяет как самому серверу, так и другим машинам в локальной сети использовать резолвер.

  • do-ip4, do-udp и do-tcp включают IPv4 и разрешают Unbound принимать DNS-запросы как по UDP, так и по TCP — стандартным транспортным протоколам DNS.

  • access-control определяет, каким клиентам разрешено пользоваться вашим DNS-сервером. Здесь только локальная машина и устройства из сети 192.168.1.0/24 могут отправлять DNS-запросы.

  • hide-identity и hide-version запрещают Unbound раскрывать свою идентификацию и номер версии при выполнении специальных DNS-запросов. Это не обязательно, но даёт небольшой плюс к безопасности, уменьшая объём информации о вашем сервере.

  • verbosity, logfile и use-syslog управляют логированием. Уровень детализации 1 даёт базовые операционные логи, а хранение их в отдельном файле упрощает диагностику.

Примечание: На Rocky Linux 10 Unbound поддерживает проверку DNSSEC из коробки. Он автоматически проверяет подписанные DNS-ответы с помощью корневого якоря доверия, поэтому в большинстве случаев дополнительная настройка DNSSEC не требуется.

Настройка форвардеров

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

Добавьте следующую секцию в конец файла конфигурации:

forward-zone:
    name: "."
    forward-addr: 1.1.1.1
    forward-addr: 9.9.9.9

В этом примере:

  • 1.1.1.1 — публичный DNS-сервер Cloudflare.

  • 9.9.9.9 — публичный DNS-сервер Quad9.

Если первый сервер недоступен, Unbound автоматически пробует следующий.

Шаг 3: Разрешение конфликтов порта 53

Перед запуском Unbound убедитесь, что никакой другой сервис не использует порт 53 — стандартный порт для DNS.

На Rocky Linux по умолчанию включён systemd-resolved, который часто создаёт локальный заглушек DNS на 127.0.0.53:53. Если этот порт уже занят, Unbound не сможет запуститься.

Чтобы проверить, какой сервис использует порт 53, выполните:

sudo ss -tulpn | grep :53

Если вы видите, что systemd-resolved слушает порт 53, отключите только его DNS-заглушку. Это освободит порт для Unbound, не затрагивая остальные функции systemd-resolved.

Создайте файл конфигурации со следующей настройкой:

sudo mkdir -p /etc/systemd/resolved.conf.d
echo -e "[Resolve]\nDNSStubListener=no" | sudo tee /etc/systemd/resolved.conf.d/no-stub.conf
sudo systemctl restart systemd-resolved

После перезапуска службы снова проверьте порт 53:

sudo ss -tulpn | grep :53

Если никто не слушает порт 53, Unbound сможет занять его при запуске на следующем шаге.

Совет: Если порт 53 занят другим DNS-сервисом, например BIND (named) или dnsmasq, остановите или перенастройте этот сервис перед стартом Unbound. Только одно приложение может одновременно слушать один и тот же IP-адрес и порт.

Шаг 4: Проверка конфигурации и запуск Unbound

Перед запуском службы проверьте файл конфигурации на синтаксические ошибки. Это поможет отловить опечатки до того, как Unbound попытается загрузить настройки.

sudo unbound-checkconf

Если конфигурация верна, команда возвращает:

unbound-checkconf: no errors in /etc/unbound/unbound.conf

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

После успешной проверки запустите службу Unbound и включите её автоматический запуск при загрузке системы:

sudo systemctl enable --now unbound

Далее убедитесь, что служба работает:

sudo systemctl status unbound

Если всё настроено правильно, вы должны увидеть состояние active (running).

● unbound.service - Unbound DNS server
     Loaded: loaded (/usr/lib/systemd/system/unbound.service; enabled)
     Active: active (running) since ...

Если служба не запустилась, изучите вывод статуса на предмет сообщений об ошибках. Также можно заглянуть в файл лога, настроенный ранее, или посмотреть системный журнал для более подробной информации:

sudo journalctl -u unbound --no-pager

Шаг 5: Разрешение DNS-трафика через межсетевой экран

Если firewalld включён, потребуется разрешить входящий DNS-трафик, чтобы другие системы в сети могли обращаться к серверу Unbound.

Выполните следующие команды:

sudo firewall-cmd --add-service=dns --permanent
sudo firewall-cmd --reload

Чтобы проверить, что правило добавлено успешно, выполните:

sudo firewall-cmd --list-services

Если всё настроено правильно, вы увидите dns в списке вместе с другими уже разрешёнными сервисами, например:

cockpit dhcpv6-client dns ssh

Теперь межсетевой экран настроен на приём DNS-запросов от клиентов, допущенных конфигурацией Unbound.

Шаг 6: Проверка работы кеширования DNS

Теперь нужно подтвердить, что Unbound действительно кеширует DNS-ответы. С самого DNS-сервера запросите домен с помощью dig, указав ваш сервер Unbound:

dig rootpath.ru@192.168.1.50

Обратите внимание на поле Query time в выводе. Первый запрос обычно занимает больше времени, потому что Unbound вынужден обращаться к вышестоящим DNS-серверам для разрешения домена.

Например:

;; Query time: 68 msec
;; SERVER: 192.168.1.50#53(192.168.1.50)

Теперь выполните ту же команду ещё раз:

dig rootpath.ru@192.168.1.50

На этот раз ответ должен быть намного быстрее, так как Unbound может вернуть результат из своего кеша вместо выполнения очередного внешнего DNS-запроса.

Например:

;; Query time: 0 msec
;; SERVER: 192.168.1.50#53(192.168.1.50)

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

Можно также протестировать с другим доменом:

dig google.com @192.168.1.50
dig github.com @192.168.1.50

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

Шаг 7: Настройка клиента на использование DNS-сервера Unbound

После того как DNS-сервер запущен и работает, осталось настроить клиентскую машину на его использование для DNS-запросов.

Если вы используете NetworkManager, укажите ваш Unbound-сервер (192.168.1.50) как предпочтительный DNS-сервер для сетевого подключения.

Сначала выведите список доступных сетевых подключений:

nmcli connection show

Запомните имя активного подключения (например, “Wired connection 1”), затем выполните:

sudo nmcli connection modify "Wired connection 1" ipv4.dns "192.168.1.50"
sudo nmcli connection modify "Wired connection 1" ipv4.ignore-auto-dns yes
sudo nmcli connection up "Wired connection 1"

Эти команды настраивают клиент на использование вашего Unbound-сервера для разрешения DNS вместо DNS-серверов, автоматически предоставляемых маршрутизатором или DHCP-сервером.

Отобразите содержимое /etc/resolv.conf:

cat /etc/resolv.conf

Вы должны увидеть ваш Unbound-сервер, например:

nameserver 192.168.1.50

Теперь проверьте разрешение DNS с клиента:

dig google.com

В выводе обратите внимание на поле SERVER. Оно должно указывать на ваш Unbound-сервер:

;; SERVER: 192.168.1.50#53(192.168.1.50)

Также можно протестировать несколько дополнительных доменов:

dig github.com
dig rootpath.ru

Если запросы выполняются успешно, а поле SERVER показывает 192.168.1.50, значит ваш клиент использует Unbound в качестве DNS-резолвера.

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

Управление и устранение неполадок Unbound

Несколько команд unbound-control покрывают большинство задач повседневного обслуживания.

  • sudo unbound-control status показывает время работы, версию и то, отвечает ли сервер на запросы.

  • sudo unbound-control stats_noreset | grep total выводит общее количество обработанных запросов и количество попаданий в кеш без сброса счётчиков.

  • sudo unbound-control dump_cache > /tmp/dns_cache_backup.txt записывает весь кеш в файл, что полезно перед плановым перезапуском.

  • sudo unbound-control lookup rootpath.ru показывает, какой форвардер ответил для конкретного домена и закеширован ли он сейчас.

  • sudo unbound-control flush rootpath.ru удаляет одну закешированную запись, не затрагивая остальные.

  • sudo unbound-control flush_zone rootpathlocal.ru очищает все закешированные записи для конкретной зоны, удобно, когда вы только что изменили внутренние DNS-записи и не хотите ждать истечения TTL.

Если клиент сообщает, что ничего не может разрешить, первым делом проверьте journalctl -u unbound -f, потому что большинство отказов связаны либо с тем, что список access-control не включает подсеть клиента, либо с тем, что форвард-зона указывает на вышестоящий резолвер, недоступный из вашей сети.

Предупреждение: Никогда не задавайте access-control: 0.0.0.0/0 allow на сервере с публичным IP. Это превратит Unbound в открытый резолвер, который любой желающий в интернете сможет использовать для DNS-амплификационных атак против третьих лиц.

Заключение

Теперь у вас настроен Unbound в качестве локального кеширующего DNS-резолвера на Rocky Linux 10. С этого момента повторные DNS-запросы для одних и тех же доменов обслуживаются напрямую из локального кеша, а не отправляются к вышестоящим DNS-серверам каждый раз.

Это снижает время DNS-запросов, сокращает лишний сетевой трафик и может повысить отзывчивость приложений, часто обращающихся к одним и тем же внешним сервисам.

А вы уже используете Unbound в production или до сих пор полагаетесь на резолвер провайдера? Расскажите в комментариях, что повлияло на ваш выбор.