Unbound на сервере: частые ошибки и решения
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 ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →