MAATRIX / Блог / Unbound на сервере: частые ошибки и решения

Unbound на сервере: частые ошибки и решения

MAATRIX

Unbound ставится как лёгкий рекурсивный резолвер с валидацией DNSSEC — часто рядом с Pi-hole или AdGuard Home, чтобы фильтр рекламы не зависел от чужих DNS-серверов. И почти сразу вылезают одни и те же проблемы: сервис не стартует, порт 53 занят, DNSSEC валит все запросы в SERVFAIL. Разберём частые ошибки Unbound на сервере по симптому, причине и решению с конкретными командами.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Unbound не стартует: ошибка конфигурации и прав доступа

Самая частая ситуация после установки: systemctl start unbound отрабатывает без видимой ошибки, а сервис через пару секунд падает в failed. Прежде чем лезть в журнал, проверьте синтаксис конфига встроенным инструментом — он ловит опечатки и неверные отступы, из-за которых Unbound откажется стартовать.

unbound-checkconf
systemctl status unbound
journalctl -u unbound -n 40 --no-pager

Если unbound-checkconf молчит и говорит «no errors», а сервис всё равно падает — смотрите на права доступа. Unbound по умолчанию работает от пользователя unbound, и если вы вручную клали файлы конфигурации, ключи DNSSEC или каталог для сокета управления через root, процесс может не иметь прав их читать. Типичная ошибка в журнале — «Could not open pidfile» или «error accessing directory».

chown -R unbound:unbound /var/lib/unbound
chown unbound:unbound /etc/unbound/unbound.conf.d/*.conf

Отдельная частая причина — конфиг разбит на несколько файлов в /etc/unbound/unbound.conf.d/, и один из включённых файлов содержит директиву в неправильной секции (например, forward-zone вне блока или лишний отступ пробелами вместо табов — YAML-подобный синтаксис Unbound к этому чувствителен). Проверяйте каждый файл unbound-checkconf <путь> по отдельности, если общая проверка не даёт зацепки.

Порт 53 занят: конфликт с systemd-resolved

На свежих Ubuntu и Debian порт 53 на localhost уже занят службой systemd-resolved, которая слушает 127.0.0.53. Unbound при попытке забиндиться на 127.0.0.1:53 или на все интерфейсы падает с ошибкой «Address already in use», и в логе это выглядит как будто сервис просто не стартует.

Проверьте, кто держит порт, перед тем как что-то менять.

ss -tulpn | grep :53
systemctl status systemd-resolved

Если в выводе ss видите процесс systemd-resolved на 53-м порту — нужно либо отключить его, либо развести порты. Для сервера, где Unbound становится основным резолвером, проще отключить systemd-resolved и переключить /etc/resolv.conf на локальный Unbound.

systemctl disable --now systemd-resolved
rm -f /etc/resolv.conf
echo "nameserver 127.0.0.1" > /etc/resolv.conf

Если резолвер нужен именно как отдельный сервис для Pi-hole или AdGuard Home на том же сервере, а systemd-resolved трогать не хочется, посадите Unbound на нестандартный порт (об этом ниже, в разделе про связку с фильтрами рекламы) — это избавляет от конфликта без отключения системной службы.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

DNSSEC validation failure и SERVFAIL на все запросы

После включения dnssec-validation в конфиге Unbound внезапно начинает отвечать SERVFAIL на все домены подряд, включая обычные google.com или github.com. Это почти всегда одна из двух причин: устаревший или отсутствующий файл корневого ключа доверия, либо разъехавшееся время на сервере.

Проверьте наличие и актуальность файла с якорем доверия.

ls -la /var/lib/unbound/root.key
unbound-anchor -v -a /var/lib/unbound/root.key

Если файла нет или он пустой, unbound-anchor создаст его заново с текущим корневым ключом IANA. Обязательно проверьте, что в конфиге прописан правильный путь к этому файлу и что владелец файла — пользователь unbound, иначе демон не сможет его прочитать при старте.

auto-trust-anchor-file: "/var/lib/unbound/root.key"

Вторая частая причина — рассинхронизация времени. DNSSEC-подписи привязаны ко времени действия, и если системные часы уехали на несколько часов (типично для VPS сразу после разворачивания образа, пока не настроен NTP), подписи выглядят «ещё не начавшими действовать» или «уже истёкшими», и Unbound честно отбраковывает ответ как невалидный.

timedatectl status
systemctl enable --now systemd-timesyncd

Если нужно быстро отладить конкретный домен, отправьте запрос напрямую и посмотрите на флаг ad (authenticated data) в ответе — его отсутствие при явно DNSSEC-подписанной зоне подтверждает, что валидация не проходит.

dig @127.0.0.1 cloudflare.com +dnssec

Unbound слушает только localhost и недоступен из сети

Резолвер работает, dig @127.0.0.1 отвечает корректно, но с других машин в локальной сети или из Pi-hole в соседнем контейнере запросы уходят в таймаут. Причина — по умолчанию Unbound слушает только 127.0.0.1 и ::1, а обращения извне блокируются на уровне access-control, даже если интерфейс формально открыт.

Проверьте текущую привязку и список разрешённых сетей.

grep -A5 "server:" /etc/unbound/unbound.conf.d/*.conf
ss -tulpn | grep unbound

Чтобы Unbound принимал запросы из локальной сети, добавьте нужный интерфейс и разрешающее правило access-control — без второго Unbound откажет в обслуживании даже с открытого порта, это разделение специально сделано так, чтобы случайно не поднять открытый резолвер наружу.

interface: 0.0.0.0
interface: ::0
access-control: 192.168.1.0/24 allow
access-control: 127.0.0.1/32 allow

После правки перезапустите сервис и проверьте с другой машины сети. Отдельно держите в уме: никогда не открывайте access-control на 0.0.0.0/0 allow для интерфейса, смотрящего в интернет — это превращает сервер в открытый рекурсивный резолвер, которым злоумышленники пользуются для DNS-амплификации в DDoS-атаках. Если серверу нужен доступ извне (например, с другого дата-центра через VPN), ограничивайте access-control конкретными подсетями, а не миром.

Unbound и Pi-hole или AdGuard Home: правильная связка портов

Классическая связка — Pi-hole или AdGuard Home как фильтр рекламы и логирование запросов, а Unbound за ним как рекурсивный резолвер, который сам ходит к корневым серверам вместо обращения к DNS от провайдера или к публичным резолверам вроде 8.8.8.8. Частая ошибка новичков — попытка посадить оба сервиса на 53-й порт одновременно, что невозможно без разведения по портам или интерфейсам.

Правильная схема: Unbound слушает только localhost на нестандартном порту 5335, а Pi-hole или AdGuard Home пересылают на него запросы как на upstream-резолвер.

server:
    interface: 127.0.0.1
    port: 5335
    do-ip4: yes
    do-udp: yes
    do-tcp: yes

В настройках Pi-hole (Settings → DNS → Custom DNS servers) укажите 127.0.0.1#5335. В AdGuard Home то же самое задаётся в разделе upstream-серверов конфига.

upstream_dns:
  - 127.0.0.1:5335

Проверить, что связка реально работает и запросы не улетают мимо Unbound к резолверам провайдера, можно через unbound-control — счётчик запросов должен расти при каждом обращении через Pi-hole или AdGuard.

unbound-control stats | grep total.num.queries

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

Медленный резолвинг и проблемы с кэшем

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

Посмотрите текущую статистику кэша и попаданий.

unbound-control stats_noreset | grep -E "cache|prefetch"

Низкое соотношение cache.hit к общему числу запросов при повторяющихся доменах говорит о том, что кэш слишком мал или записи вытесняются раньше истечения TTL. Увеличьте размер кэша сообщений и RRset, особенно если на сервере крутится не один клиент, а целая сеть за Pi-hole или AdGuard.

msg-cache-size: 128m
rrset-cache-size: 256m
prefetch: yes
prefetch-key: yes

Директива prefetch: yes заставляет Unbound обновлять запись в кэше заранее, до истечения TTL, если домен активно запрашивается — это сглаживает задержку для часто посещаемых сайтов ценой чуть большей фоновой нагрузки на сеть. Ориентировочно на выделенном сервере с несколькими гигабайтами памяти эти значения кэша не создают заметной нагрузки, но точные цифры задержек и попаданий сильно зависят от вашего трафика и профиля запросов — не берите чужие бенчмарки как гарантию для своего случая.

Если проблема не в кэше, а в самой цепочке резолвинга (медленно отвечают конкретные upstream или корневые серверы), включите временную отладку с повышенным уровнем логирования.

verbosity: 3
journalctl -u unbound -f

После диагностики обязательно верните verbosity к 1, иначе журнал быстро разрастётся — подробный уровень логирования пишет запись почти на каждый запрос.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Unbound не стартует, а unbound-checkconf не находит ошибок — что делать?

Проверьте права на /var/lib/unbound и файлы конфига: сервис работает от пользователя unbound, и если файлы созданы от root, демон не сможет их открыть. Выполните chown -R unbound:unbound /var/lib/unbound.

Порт 53 занят, хотя Unbound единственный DNS-сервис на машине?

Почти наверняка его держит systemd-resolved на 127.0.0.53. Проверьте ss -tulpn | grep :53 и либо отключите systemd-resolved, либо разведите сервисы по портам.

Все домены отвечают SERVFAIL после включения DNSSEC — с чего начать?

С проверки файла /var/lib/unbound/root.key через unbound-anchor -v и системного времени через timedatectl status. Обе причины дают одинаковый симптом — сплошной SERVFAIL.

Как проверить, что Pi-hole или AdGuard Home реально используют мой Unbound, а не резолвят напрямую?

Смотрите счётчик unbound-control stats | grep total.num.queries до и после DNS-запроса через фильтр. Если он не растёт — upstream в настройках фильтра указывает не туда.

Безопасно ли открывать Unbound на все интерфейсы?

Только с явными ограничениями access-control по конкретным подсетям. Открытый резолвер на 0.0.0.0/0 allow, смотрящий в интернет, злоумышленники используют для DNS-амплификации в DDoS-атаках.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →