Выберите продукт

Debian/Ubuntu: как устранить конфликт systemd-resolved DNSStubListener с BIND9, dnsmasq и AdGuard Home

Если в Debian или Ubuntu DNS-сервер не стартует из-за ошибки port 53 busy, часто причина в systemd-resolved с локальным слушателем на 127.0.0.53. Разберём, как это проверить, когда отключать DNSStubListener и как без путаницы запустить bind9, dnsmasq или AdGuard Home.
Debian/Ubuntu: как устранить конфликт systemd-resolved DNSStubListener с BIND9, dnsmasq и AdGuard Home

На Debian и Ubuntu одна из самых частых причин ошибки port 53 busy — не BIND9, не dnsmasq и не AdGuard Home, а штатный сервис systemd-resolved. Он поднимает локальный stub-resolver и по умолчанию слушает адрес 127.0.0.53:53. Пока это поведение не учтено, любой локальный DNS-сервис пытается занять тот же порт и падает при запуске.

Проблема особенно неприятна тем, что внешне всё выглядит неоднозначно. Ставите bind9, проверяете конфиг, запускаете службу — и получаете отказ. Устанавливаете AdGuard Home, а мастер сообщает, что DNS-порт уже занят. Поднимаете dnsmasq для кэша, локальных зон или резолвинга контейнеров — и снова конфликт.

Суть в том, что systemd-resolved — это не просто клиентская утилита для DNS. В Debian и Ubuntu он часто интегрирован в сетевую подсистему и обслуживает системное разрешение имён через локальную точку входа. Симлинк /etc/resolv.conf при этом нередко указывает на файл, где записан nameserver 127.0.0.53.

Когда на сервере нужен полноценный локальный DNS-демон, возникает выбор: оставить systemd-resolved как есть и привязать ваш DNS-сервис к другому адресу, либо отключить DNSStubListener и отдать 53-й порт основному демону. Второй вариант чаще оказывается чище, особенно если сервер реально должен обслуживать DNS-запросы сам.

Важно не путать две задачи: системное разрешение имён для самого хоста и работу DNS-службы как сервера. Их можно совместить, но только если заранее понимать, кто слушает 53-й порт, кто формирует /etc/resolv.conf и куда смотрят локальные приложения.

Как понять, что виноват именно systemd-resolved

Первый симптом — ошибка запуска DNS-службы с текстом про занятый адрес или порт. Формулировка зависит от демона: address already in use, failed to listen on port 53, cannot bind socket. Но диагноз надо подтверждать, а не гадать.

Начните с проверки, кто реально слушает 53-й порт:

ss -ltnup '( sport = :53 )'
ss -lnup '( sport = :53 )'
lsof -i :53 -n -P

Если в выводе есть процесс systemd-resolve или systemd-resolved на 127.0.0.53:53, источник конфликта найден. Часто картина выглядит так: TCP и UDP 53 слушаются только на loopback-адресе 127.0.0.53, но этого уже достаточно, чтобы другой сервис не смог занять тот же сокет на всех интерфейсах или на 127.0.0.1.

Дальше полезно посмотреть статус сервиса:

systemctl status systemd-resolved
resolvectl status

Команда resolvectl status покажет, какие upstream DNS используются, на каких интерфейсах, включён ли локальный stub и как вообще организовано разрешение имён на текущем хосте.

Отдельно проверьте, куда указывает /etc/resolv.conf:

ls -l /etc/resolv.conf
cat /etc/resolv.conf

В типовой конфигурации Ubuntu вы увидите либо симлинк на файл вида /run/systemd/resolve/stub-resolv.conf, либо другой файл из каталога /run/systemd/resolve/. Если внутри указан nameserver 127.0.0.53, это ещё один явный признак активного DNSStubListener.

Главная ошибка на этом этапе — сразу отключать сервисы наугад. Сначала выясните, кто слушает порт 53, куда смотрит /etc/resolv.conf и нужен ли серверу локальный DNS именно как сервис, а не просто как клиентский резолвер.

Почему конфликт возникает даже при прослушивании только 127.0.0.53

На первый взгляд может показаться, что адрес 127.0.0.53 не мешает, ведь это не 0.0.0.0 и не внешний IP. Но для DNS-сервисов это вполне реальный конфликт. Многие демоны по умолчанию хотят слушать либо все адреса, либо весь loopback, либо одновременно и IPv4, и IPv6. Если сокет уже занят на нужном адресе или комбинации адрес и порт, сервис не стартует.

Например, bind9 часто пытается занять 53-й порт на всех доступных интерфейсах. dnsmasq обычно поднимается как локальный DNS-кэш и тоже претендует на 53-й порт на loopback. AdGuard Home при стандартной настройке хочет слушать DNS глобально, чтобы принимать запросы от клиентов сети. Во всех трёх случаях локальный stub от systemd-resolved становится препятствием.

Есть и второй слой проблемы: после отключения stub многие забывают, что сам сервер тоже должен продолжить резолвить домены. Если просто освободить порт 53, но не привести в порядок /etc/resolv.conf, можно получить ситуацию, когда DNS-сервер уже стартует, а сам хост не может выполнить apt update, скачать пакеты или достучаться до внешних API по имени.

Именно поэтому правильная схема — не просто «освободить порт», а последовательно проверить: кто слушает, кто обслуживает системный DNS и кто должен отвечать на запросы после изменений.

Проверка конфликта systemd-resolved с локальным DNS-сервисом на 53-м порту

Рабочие схемы решения

На практике используются три базовых подхода. Выбор зависит от роли сервера и от того, нужен ли systemd-resolved как часть локальной схемы разрешения имён.

Вариант 1. Отключить только DNSStubListener и оставить systemd-resolved

Это самый удобный и обычно самый аккуратный сценарий. Сервис systemd-resolved продолжает работать, но перестаёт слушать локальный порт 53 на 127.0.0.53. В результате освобождается сокет для BIND9, dnsmasq или AdGuard Home, а системная логика resolved при желании сохраняется.

Откройте конфигурацию:

sudo editor /etc/systemd/resolved.conf

Добавьте или измените параметр:

[Resolve]
DNSStubListener=no

После этого перезапустите сервис:

sudo systemctl restart systemd-resolved

Затем обязательно проверьте, куда теперь должен смотреть /etc/resolv.conf. Обычно после отключения stub правильнее использовать файл с реальными upstream DNS, а не с адресом 127.0.0.53. Во многих случаях подходит такая привязка:

sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

Проверьте результат:

cat /etc/resolv.conf
resolvectl status
ss -lnup '( sport = :53 )'

После этого можно запускать нужный DNS-сервис и повторно смотреть, кто слушает порт 53.

Этот вариант хорош тем, что меняет минимум логики в системе. Он особенно удобен, если DNS для хоста приходит через DHCP, netplan, NetworkManager или cloud-init, а вам нужно лишь убрать конфликт по порту.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Вариант 2. Полностью отключить systemd-resolved

Этот путь уместен, когда сервер сам становится основным DNS-резолвером или authoritative либо recursive-сервером и промежуточный слой systemd-resolved уже не нужен. Например, вы хотите, чтобы локальный dnsmasq или BIND9 обслуживал и сам хост, и внешних клиентов.

Последовательность такая:

sudo systemctl disable --now systemd-resolved

Далее нужно вручную привести в порядок /etc/resolv.conf. Если сервер будет резолвить через локальный DNS-сервис, можно указать:

nameserver 127.0.0.1

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

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

Вариант 3. Развести адреса прослушивания

Иногда systemd-resolved лучше оставить без изменений, а DNS-службу привязать к конкретному адресу. Такой подход встречается реже, но бывает полезен на сложных хостах, где локальный stub нужен приложениям, а DNS-сервис должен обслуживать только внешний интерфейс.

Например, можно заставить BIND9 слушать только адрес сервера в локальной сети или только публичный IP, а не весь loopback. Аналогично для dnsmasq и AdGuard Home можно ограничить список адресов и интерфейсов прослушивания.

Минус здесь в том, что конфигурация становится менее очевидной. Через пару месяцев легко забыть, почему сервис не отвечает на 127.0.0.1 или почему локальные запросы идут не туда. Поэтому для одиночного сервера обычно проще отключить DNSStubListener, чем жить с хитрым разносом адресов.

Пошагово: BIND9, если мешает 127.0.0.53

Для bind9 самый типичный сценарий — BIND должен слушать 53-й порт полноценно, а systemd-resolved только мешает. В большинстве случаев практичнее отключать именно DNSStubListener, а не весь systemd-resolved.

Базовый порядок действий:

  • Проверить занятость порта 53.
  • Отключить DNSStubListener в resolved.conf.
  • Исправить /etc/resolv.conf.
  • Проверить конфиг BIND9.
  • Запустить сервис и убедиться, что он слушает нужные интерфейсы.

Проверка конфига BIND9:

sudo named-checkconf
sudo named-checkzone example.local /etc/bind/db.example.local

Запуск и проверка:

sudo systemctl restart bind9
sudo systemctl status bind9
ss -lnup '( sport = :53 )'

Если BIND9 нужен и для самого сервера как резолвер, можно после запуска прописать в /etc/resolv.conf локальный адрес, который слушает named. Но только после проверки реального ответа на запросы, иначе получите циклическую поломку: DNS-сервис не работает, а система без резолвинга уже не может нормально чиниться.

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

Пошагово: dnsmasq на Debian/Ubuntu

dnsmasq часто ставят ради кэширующего DNS, локальных записей, PXE или интеграции с контейнерами и виртуалками. Конфликт с systemd-resolved здесь почти классический: оба хотят быть локальным DNS на 53-м порту.

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

Минимальная проверка сервиса:

sudo systemctl restart dnsmasq
sudo systemctl status dnsmasq
journalctl -u dnsmasq -n 50 --no-pager

Если после отключения stub dnsmasq стартует, но сам сервер перестаёт резолвить имена, почти всегда проблема не в dnsmasq, а в неправильном /etc/resolv.conf. Либо там остался 127.0.0.53, хотя stub уже выключен, либо указан 127.0.0.1, но dnsmasq не слушает loopback.

Полезная мысль: когда используете dnsmasq как локальный кэш, не пытайтесь одновременно держать два локальных резолвера с пересекающимися ролями. Это почти всегда рождает трудноуловимые петли, таймауты и разный результат у разных приложений.

Настройка BIND9, dnsmasq и AdGuard Home после освобождения 53-го порта

Пошагово: AdGuard Home и занятый port 53

С AdGuard Home ситуация особенно частая, потому что продукт ориентирован на роль основного DNS-сервера для хоста или сети. После установки мастер настройки пытается занять 53-й порт и натыкается на локальный stub от systemd-resolved.

Если видите сообщение о том, что DNS нельзя запустить, сначала не трогайте сам AdGuard Home. Сначала освободите порт 53 со стороны systemd-resolved. То есть снова редактируете resolved.conf, задаёте DNSStubListener=no, перезапускаете службу и перепроверяете, что на 127.0.0.53:53 больше никто не слушает.

После этого уже перезапускайте AdGuard Home и смотрите его статус. Если планируете, чтобы сам сервер тоже пользовался AdGuard Home как DNS, убедитесь, что в /etc/resolv.conf указан адрес, который реально слушает сервис. Чаще всего это 127.0.0.1 или адрес конкретного интерфейса.

Здесь есть важный практический момент: если AdGuard Home слушает только внешний IP, а в /etc/resolv.conf вы прописали 127.0.0.1, резолвинг на хосте работать не будет. И наоборот: если сервис ограничен loopback, клиенты сети до него не достучатся. Всегда сверяйте конфиг слушающих адресов с тем, как реально должны ходить запросы.

Для публичных сервисов и панелей управления не забывайте и про SSL-сертификаты, чтобы административный доступ к веб-интерфейсам был защищён.

FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Что делать с /etc/resolv.conf после изменений

Большинство проблем после «успешного» устранения конфликта начинаются именно тут. Админ видит, что порт 53 освободился и сервис стартовал, но не замечает, что системный DNS у самого хоста сломан.

Запомните простое правило. Если systemd-resolved остаётся активным, но DNSStubListener выключен, /etc/resolv.conf обычно должен ссылаться не на stub-файл, а на файл с реальными DNS-серверами. Если же systemd-resolved полностью отключён, /etc/resolv.conf должен либо управляться другим механизмом, либо содержать корректные nameserver-записи вручную.

После любых правок проверьте:

getent hosts debian.org
resolvectl query debian.org
dig debian.org
ping -c 1 debian.org

Не все команды одинаково важны в каждой системе, но вместе они быстро показывают, работает ли резолвинг на уровне libc, на уровне resolved и на уровне прямого DNS-запроса.

Если после правок перестал работать apt, почти всегда причина в том, что /etc/resolv.conf остался привязан к 127.0.0.53, хотя stub уже отключён, либо ссылается на локальный DNS, который ещё не слушает нужный адрес.

Как проверить, что всё настроено правильно

Хорошая проверка состоит из трёх уровней: порт, служба, резолвинг.

  • Порт: кто слушает 53 и на каких адресах.
  • Служба: запущен ли нужный демон без ошибок в журнале.
  • Результат: может ли сам хост и клиенты получить DNS-ответ.

Минимальный набор команд после изменений:

ss -lnup '( sport = :53 )'
systemctl status systemd-resolved
systemctl status bind9
systemctl status dnsmasq
journalctl -u systemd-resolved -n 50 --no-pager
cat /etc/resolv.conf
getent hosts ubuntu.com

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

Типичные ошибки и как их избежать

Самая популярная ошибка — отключить systemd-resolved полностью там, где достаточно было лишь задать DNSStubListener=no. Это не всегда критично, но часто создаёт лишнюю ручную работу с сетью и resolv.conf.

Вторая ошибка — править /etc/resolv.conf вручную, не проверив, не перезаписывает ли его другой компонент: cloud-init, NetworkManager, netplan, dhclient или сам systemd-resolved. Если файл каждый раз возвращается в старое состояние, лечить надо источник генерации, а не только результат.

Третья ошибка — запускать локальный DNS-сервер и тут же направлять системный резолвинг на него, не проверив upstream-конфигурацию. Для dnsmasq, BIND9 и AdGuard Home это заканчивается либо таймаутами, либо рекурсией в самого себя.

Четвёртая ошибка — забыть про IPv6. Даже если конфликт виден на 127.0.0.53, ваш DNS-демон может пытаться дополнительно слушать ::1 или все IPv6-интерфейсы. Поэтому проверяйте не только IPv4-сокеты, но и общий список прослушивания.

Если параллельно на сервере крутятся веб-службы, контейнеры и несколько стеков приложений, полезно заранее разделять роли по сервисам и адресам. Это тот же принцип, который помогает и при настройке нескольких PHP-FPM pool в Nginx: чем прозрачнее схема, тем проще диагностика и сопровождение.

Какой вариант выбрать на практике

Если нужен короткий практический вывод, он такой.

  • Для большинства случаев с bind9, dnsmasq и AdGuard Home на Debian и Ubuntu достаточно отключить DNSStubListener в resolved.conf.
  • Полностью отключать systemd-resolved стоит только если вы точно понимаете, как дальше будет обслуживаться системный DNS.
  • Разнос по адресам полезен в нестандартных схемах, но усложняет сопровождение.

На сервере, где DNS-сервис играет важную роль для инфраструктуры, лучше выбирать конфигурацию с минимальным числом скрытых посредников. Чем понятнее цепочка «кто слушает 53-й порт, кто обслуживает локальный хост, кто ходит к upstream», тем проще сопровождение и аварийное восстановление.

Если вы разворачиваете собственный DNS, фильтрацию запросов, split-horizon или локальный рекурсор на отдельном сервере, особенно удобно делать это в изолированном окружении. В таких сценариях часто практичнее использовать отдельный VDS, чтобы DNS-служба не конфликтовала с уже работающим набором системных сервисов.

Короткий чек-лист для устранения конфликта

  1. Проверьте, кто слушает порт 53 через ss или lsof.
  2. Убедитесь, что виноват systemd-resolved и адрес 127.0.0.53.
  3. Если нужен локальный DNS-сервис, задайте DNSStubListener=no в /etc/systemd/resolved.conf.
  4. Перезапустите systemd-resolved.
  5. Исправьте /etc/resolv.conf под новую схему.
  6. Запустите BIND9, dnsmasq или AdGuard Home.
  7. Проверьте не только статус сервиса, но и реальное разрешение имён на хосте.

Если пройти эти шаги именно в таком порядке, проблема port 53 busy в Debian и Ubuntu обычно решается быстро и без побочных эффектов. А главное — без ситуации, когда DNS-сервер вроде бы поднялся, но сам сервер после этого остался без DNS.

Поделиться статьей

Вам будет интересно

Debian/Ubuntu: конфликт systemd-resolved DNSStubListener на 127.0.0.53 с dnsmasq, Unbound и BIND OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: конфликт systemd-resolved DNSStubListener на 127.0.0.53 с dnsmasq, Unbound и BIND

Если локальный DNS в Debian или Ubuntu не стартует с ошибкой address already in use, причина часто в systemd-resolved и DNSStubLis ...
Debian/Ubuntu: как исправить NFS mount.nfs: access denied by server while mounting OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить NFS mount.nfs: access denied by server while mounting

Ошибка mount.nfs: access denied by server while mounting в Debian и Ubuntu обычно указывает на проблему на стороне NFS-сервера: не ...
Debian/Ubuntu: как исправить Device is busy у Docker network, volume и namespace OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить Device is busy у Docker network, volume и namespace

Если Docker на Debian или Ubuntu отвечает Device is busy при удалении сети, тома или namespace, причина обычно в живом процессе, о ...