На Debian и Ubuntu одна из самых частых причин проблем с локальным DNS — не сам dnsmasq, unbound или bind9, а служба systemd-resolved. Она может поднимать локальный stub-resolver на адресе 127.0.0.53:53, из-за чего другой DNS-демон уже не может занять порт 53 на loopback или на нужном интерфейсе.
В результате вы видите знакомые сообщения вроде address already in use, а затем начинаются хаотичные попытки переписать /etc/resolv.conf, перенести сервис на другой адрес или отключить всё подряд. Обычно это только усложняет картину.
Проблема неприятна тем, что система может выглядеть почти рабочей: apt то резолвит имена, то нет, локальный кэширующий резолвер стартует через раз, а контейнеры и сам хост используют разные DNS-цепочки. Если не понять архитектуру, получается классический зоопарк из нескольких DNS-компонентов.
Разберём, что именно делает systemd-resolved, зачем ему нужен DNSStubListener, почему используется адрес 127.0.0.53, как диагностировать конфликт и как выбрать нормальную схему работы с dnsmasq, unbound или bind9 на сервере Debian/Ubuntu.
Что такое systemd-resolved и почему он слушает 127.0.0.53
systemd-resolved — это системный сервис резолвинга имён. Он умеет принимать локальные DNS-запросы, кэшировать ответы, использовать разные upstream DNS-серверы и интегрироваться с сетевыми компонентами системы. В Ubuntu он часто включён по умолчанию, а в Debian его поведение зависит от версии и профиля установки.
Когда включён параметр DNSStubListener, служба слушает локальный адрес 127.0.0.53 на порту 53. Обычно в /etc/resolv.conf при этом прописывается nameserver 127.0.0.53, и приложения отправляют запросы туда, а уже systemd-resolved пересылает их на реальные DNS-серверы.
Сам адрес
127.0.0.53не является ошибкой. Конфликт начинается только тогда, когда другой DNS-сервис тоже пытается слушать порт 53 на том же хосте.
Типичный сценарий: вы ставите dnsmasq как локальный кэш, unbound как validating resolver или bind9 для форвардинга и локальных зон. Сервис не стартует, потому что часть DNS-сокетов уже занята systemd-resolved.
Как проявляется конфликт DNSStubListener
Симптомы обычно однотипны: служба не запускается после установки или после изменения конфигурации, в логе есть ошибка привязки адреса, а команда диагностики показывает активный listener на 127.0.0.53:53.
- не стартует
dnsmasq,unboundилиbind9; - в журнале есть
address already in use; ssилиlsofпоказывают слушатель на порту 53;/etc/resolv.confуказывает на127.0.0.53, хотя вы рассчитывали использовать127.0.0.1;- после отключения одного сервиса резолвинг ломается полностью.
Сначала проверьте, кто именно занял порт 53:
ss -ltnup '( sport = :53 )'
ss -lnup | grep ':53'
lsof -i :53 -nP
Затем проверьте статус резолвера и текущую схему:
systemctl status systemd-resolved
resolvectl status
readlink -f /etc/resolv.conf
cat /etc/resolv.conf
Если видите systemd-resolved на 127.0.0.53:53, а /etc/resolv.conf ведёт на stub-файл, значит у вас активна стандартная схема со stub listener.

Главная ошибка: держать два локальных резолвера на одном порту
Суть конфликта проста: на одном IP и одном порту не могут одновременно слушать два процесса. Поэтому схема «оставлю включённым systemd-resolved и рядом подниму unbound или dnsmasq на localhost:53» почти всегда заканчивается проблемой.
Нужно не лечить симптом, а выбрать одну рабочую архитектуру:
- оставить
systemd-resolvedкак локальный stub, а второй DNS-сервис слушать на другом адресе или порту; - отключить только
DNSStubListener, но оставить самsystemd-resolvedв системе; - полностью отключить
systemd-resolvedи отдать роль локального DNS другому демону; - запустить альтернативный резолвер только на конкретном интерфейсе без пересечения по адресам.
Правильное решение зависит от роли сервера. Для простого кэша достаточно одного DNS-компонента, а для валидации DNSSEC, форвардинга или локальных зон уже нужен осознанный выбор между
unbound,dnsmasqиbind9.
Если вы разворачиваете инфраструктуру на VDS, такую схему лучше определить сразу после базовой установки системы. Тогда и отладка, и автоматизация будут заметно проще.
Вариант 1: отключить только DNSStubListener
Это самый аккуратный путь, если вам нужен dnsmasq, unbound или bind9 на localhost:53, но вы не хотите полностью удалять или отключать systemd-resolved.
Откройте конфигурацию:
sudo editor /etc/systemd/resolved.conf
Добавьте или измените параметр:
[Resolve]
DNSStubListener=no
После этого перезапустите службу:
sudo systemctl restart systemd-resolved
ss -lnup | grep ':53'
Но здесь есть важный нюанс: после отключения stub listener нужно проверить, куда теперь указывает /etc/resolv.conf. Если он всё ещё ссылается на файл с nameserver 127.0.0.53, резолвинг сломается.
Один из безопасных вариантов — направить /etc/resolv.conf на runtime-файл systemd-resolved с реальными upstream DNS:
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
readlink -f /etc/resolv.conf
cat /etc/resolv.conf
Если же вы хотите, чтобы система ходила в ваш локальный резолвер, тогда в /etc/resolv.conf должен быть указан уже адрес этого сервиса, например 127.0.0.1.
Вариант 2: полностью отключить systemd-resolved
Такой путь часто выбирают на серверах, где DNS должен быть полностью предсказуемым и управляться только через dnsmasq, unbound или bind9. На минимальных установках это часто проще сопровождать.
Базовая последовательность выглядит так:
sudo systemctl disable --now systemd-resolved
sudo rm -f /etc/resolv.conf
sudo editor /etc/resolv.conf
Затем создайте обычный файл, например:
nameserver 127.0.0.1
options edns0 trust-ad
После этого запускайте ваш DNS-демон и проверяйте, что он реально отвечает на запросы.
У этого варианта есть нюанс: некоторые компоненты сети могут ожидать наличие systemd-resolved или пытаться перегенерировать DNS-настройки. Поэтому после отключения проверьте, кто у вас управляет сетью: systemd-networkd, Netplan, NetworkManager, cloud-init или свои скрипты.
Как настроить dnsmasq без конфликта
dnsmasq часто используют как лёгкий кэширующий DNS с локальными записями. Если он должен стать основным резолвером на сервере, лучше заранее отключить stub listener или сам systemd-resolved.
Минимальная конфигурация может выглядеть так:
listen-address=127.0.0.1
bind-interfaces
no-resolv
server=1.1.1.1
server=8.8.8.8
cache-size=1000
После настройки проверьте запуск:
sudo systemctl restart dnsmasq
sudo systemctl status dnsmasq
dig @127.0.0.1 example.org
getent hosts example.org
Если хотите использовать локальные записи и кэш, но без лишнего усложнения, dnsmasq обычно достаточно. Главное — не смешивать его с другим локальным резолвером без чёткой необходимости.

Как настроить Unbound без конфликта
Unbound удобен, когда нужен validating resolver с DNSSEC, понятной моделью кэширования и предсказуемой серверной логикой. На Debian и Ubuntu это один из самых популярных вариантов для локального DNS на хосте.
Базовые параметры выглядят примерно так:
server:
interface: 127.0.0.1
port: 53
do-ip4: yes
do-udp: yes
do-tcp: yes
access-control: 127.0.0.0/8 allow
Проверка после настройки:
unbound-checkconf
sudo systemctl restart unbound
sudo systemctl status unbound
dig @127.0.0.1 example.org
getent hosts example.org
Если systemd-resolved ещё остаётся в системе, полезно дополнительно проверить, не указывает ли /etc/resolv.conf на старый stub listener. Именно здесь чаще всего и прячется причина странного поведения.
Как настроить bind9 без конфликта
bind9 нужен там, где кроме обычного резолвинга требуются локальные зоны, ACL, forwarding, recursion и более классическая DNS-архитектура. Но и у него тот же принцип: если named должен занять 53-й порт, никто другой не должен держать этот сокет.
Пример базовой конфигурации прослушивания:
options {
directory "/var/cache/bind";
listen-on { 127.0.0.1; };
listen-on-v6 { ::1; };
recursion yes;
allow-query { localhost; };
};
Проверка:
sudo named-checkconf
sudo systemctl restart bind9
sudo systemctl status bind9
ss -lnup | grep ':53'
dig @127.0.0.1 example.org
Если BIND должен обслуживать не только локальный хост, а ещё и сеть, указывайте нужные адреса явно и не оставляйте прослушивание на всех интерфейсах без необходимости.
Что делать с resolv.conf, чтобы не сломать DNS после фикса
Самая частая вторая ошибка после освобождения порта 53 — забыть про /etc/resolv.conf. Сервис уже стартует, а система продолжает спрашивать DNS у старого адреса.
Здесь полезно мыслить очень просто: /etc/resolv.conf должен указывать туда, где реально доступен рабочий DNS-сервис для приложений.
nameserver 127.0.0.53— когда используется активный stub listener отsystemd-resolved;nameserver 127.0.0.1— когда основной локальный резолвер этоdnsmasq,unboundилиbind9;- внешние DNS-серверы — когда локального резолвера на машине нет.
Если после изменения схемы всё как будто работает по-старому, это ещё не победа. Часто оказывается, что приложения по-прежнему используют старый
resolv.conf, а новый локальный DNS вообще не участвует в цепочке.
Если на сервере используются свои зоны, внешние записи и сертификаты, DNS лучше держать в полностью предсказуемом состоянии. В смежной теме может пригодиться материал про автоматизацию wildcard SSL через DNS-01, где корректный локальный и внешний DNS особенно важен.
Быстрый алгоритм диагностики
Если локальный DNS-демон падает с address already in use, пройдите короткий чек-лист:
- Проверьте, кто слушает порт 53 через
ssилиlsof. - Посмотрите статус
systemd-resolved. - Проверьте, куда указывает
/etc/resolv.conf. - Определите, кто должен быть главным DNS-компонентом на сервере.
- Либо отключите
DNSStubListener, либо полностью выключитеsystemd-resolved. - Приведите
resolv.confв соответствие новой схеме. - Проверьте запросы через
digиgetent.
Этот порядок почти всегда быстрее бессистемного редактирования конфигов и помогает не получить ситуацию, когда демон стартует, но система его не использует.
Какую схему выбрать на практике
Нужен просто стабильный локальный кэш
Обычно достаточно либо systemd-resolved, либо dnsmasq. Два локальных резолвера одновременно чаще мешают, чем помогают.
Нужен validating resolver и предсказуемое поведение
Чаще всего лучше выбрать unbound и отключить stub listener либо сам systemd-resolved.
Нужны локальные зоны и классический DNS-серверный стек
Тогда логичен bind9, особенно если нужно явно разделять рекурсию, форвардинг и авторитативные зоны.
Это минимальный сервер без desktop-компонентов
Чем меньше скрытой автоматизации, тем проще сопровождение. Поэтому на сервере удобнее одна ясная DNS-схема без наложения ролей.
На практике это особенно заметно на проектах, размещённых на виртуальном хостинге или на отдельном сервере, где любой сетевой сбой сразу отражается на приложении. Понятный DNS-стек экономит время и при отладке, и при миграциях.
Итог
Конфликт systemd-resolved с dnsmasq, unbound или bind9 — типовая история для Debian и Ubuntu. Корень проблемы почти всегда один: активный DNSStubListener занимает 127.0.0.53:53, а второй DNS-сервис пытается слушать тот же порт или пересекающийся адрес.
Правильный путь — выбрать одну понятную архитектуру. Либо оставляете systemd-resolved и не поднимаете рядом второй локальный резолвер на том же порту, либо отключаете DNSStubListener, либо полностью переходите на dnsmasq, unbound или bind9. И обязательно синхронизируете это с /etc/resolv.conf.
Если запомнить только одну мысль, то она такая: ошибка address already in use у DNS-демона почти всегда начинается с двух вопросов — кто сейчас слушает порт 53 и куда указывает /etc/resolv.conf. Ответ на них обычно и даёт половину решения.


