Собственный DNS-сервер Unbound в Linux (Debian / Ubuntu)
Собственный DNS-сервер для локальной сети или VPN-сервера в режиме переадресации запросов на публичный DNS через защищённый протокол DoT (DNS-over-TLS) эффективно кэширует запросы, сокращает их количество и блокирует рекламные домены. Это повышает безопасность пользователей локальной сети и самого сервера.
По умолчанию протокол DNS использует порт 53, и весь трафик передаётся в открытом незашифрованном виде. Если на устройстве указать публичный DNS-сервер (например, 1.1.1.1), трафик будет передаватся в открытом виде по порту 53. Интернет провайдеры, операторы связи или злоумышленники (например, при MITM-атаке) могут видеть, к какому домену обращались, и подменить ответ с IP-адресом сайта или сервиса.
Для решения этой проблемы безопасности были разработаны защищённые DNS протоколы DoH (DNS-over-HTTPS), DoT (DNS-over-TLS). Данные протоколы можно настроить на части устройств (телефоны, компьютеры), а на некоторых устройствах (телевизоры и TV-приставки) настройка затруднительна или вовсе невозможна.
Проще и удобнее использовать собственный DNS-сервер Unbound, который переадресовывает запросы на публичные DNS-серверы по защищённым протоколам. Дополнительно можно настроить блокировку рекламы.
Установка и настройка Unbound как DNS-сервера для локальной сети будет показана на примере операционной системы Debian 13. Настройка происходит аналогично в других дистрибутивах Linux (Ubuntu, Arch, Fedora), только различаются команды установки.
Все действия выполняются от имени пользователя root или с его привилегиями через sudo
su -
sudo -i
1. Установка Unbound
Устанавливаем Unbound в Debian/Ubuntu
apt install unbound

Дожидаемся окончания установки.
2. Проверка необходимых ключей и сертификатов
Для работы DNSSEC необходим корневой якорь (ключа) доверия DNSKEY. Во время установки Unbound в Debian также был установлен пакет dns-root-data, внутри которого содержится необходимые корневые подсказки и якоря доверия. В других операционных системах будет установлен аналогичный пакет.
Проверяем наличие корневого ключа в Debian и подобных дистрибутивах:
ls -l /usr/share/dns/root.key
Если якорь доверия отсутствует, устанавливаем утилиту unbound-anchor
apt install unbound-anchor
Получаем корневой якорь доверия для DNSSEC
unbound-anchor -a /var/lib/unbound/root.key
Параметр -a указывает путь для сохранения файла.
Для доступа к публичным DNS-серверам через протокол DoT (DNS-over-TLS), необходим пакет распространённых центров сертификации. В большинстве дистрибутивов Linux он уже предустановлен.
Если ca-certificates вдруг отсутствует, то устанавливаем его
apt install ca-certificates
3. Настройка и конфигурация Unbound (unbound.conf)
Основной файл конфигурации unbound.conf находится по адресу /etc/unbound/unbound.conf
Открываем файл конфигурации и редактируем его
nano /etc/unbound/unbound.conf
В данной конфигурации будут описаны основные параметры для настройки своего DNS-сервера Unbound внутри локальной сети в режиме переадресации запросов через DNS-over-TLS на публичный DNS-сервер. Если разрешить слушать только 127.0.0.1, то это будет локальный DNS-сервер.
Строки относящиеся к своему VPN серверу, настройки выдачи IP адресов для домена, черный список доменов показаны как пример возможной настройки и их указывать необязательно, если ничего из этого не планируется использовать.
### Настройка DNS-сервера Unbound ###
server:
# Интерфейсы прослушивания DNS-сервером Unbound. По умолчанию localhost (127.0.0.1 и ::1)
# Для прослушивания всех интерфейсов необходимо указать 0.0.0.0 и ::0
# IP-адрес localhost (127.0.0.1)
interface: 127.0.0.1
# IP-адрес сетевой карты локальной сети (192.168.0.1 в моем случае)
interface: 192.168.0.1
# Интерфейс VPN сервера WireGuard или его IP-адрес
#interface: wg0
# Разрешаем использовать IPv4. По умолчанию: yes (включено)
do-ip4: yes
# Запрещаем использовать IPv6. По умолчанию: yes (включено)
do-ip6: no
# Разрешаем доступ к DNS-серверу IP-адресам локальной сети (192.168.0.0/24 в моем случае)
access-control: 192.168.0.0/24 allow
# Разрешаем доступ к DNS-серверу всем клиентам VPN (wg0 в моем случае)
#access-control: wg0 allow
# Имя пользователя от которого запускать Unbound
username: unbound
# Не отвечать на запросы о сведениях, версии DNS-сервера Unbound
hide-identity: yes
hide-version: yes
# Максимальное время кэширования. По умолчанию: 86400 (24 часа)
cache-max-ttl: 86400
# Минимальное время кэширования. По умолчанию: 0 (используется TTL из DNS-ответа)
cache-min-ttl: 3600
# Предварительная загрузка часто запрашиваемых DNS-записей у которых истекает TTL. По умолчанию: no (выключено)
prefetch: yes
# Исключаем из ответов DNS-сервера адреса диапазона частных IP-адресов
# Это необходимо для защиты от уязвимости "DNS rebinding"
private-address: 10.0.0.0/8
private-address: 172.16.0.0/12
private-address: 192.168.0.0/16
private-address: 169.254.0.0/16
private-address: fd00::/8
private-address: fe80::/10
private-address: ::ffff:0:0/96
# Путь к корневому ключу, для DNSSEC
auto-trust-anchor-file: "/var/lib/unbound/root.key"
# Путь к сертификатам центров сертификации, для DNS-over-TLS
tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt
# Выдаваем для домена свой IP-адрес (аналог hosts)
#local-zone: "notby.net." redirect
#local-data: "notby.net. IN A 192.168.0.1"
# Подключение файла черного списка доменов (подробнее в 9 разделе статьи)
#include: /etc/unbound/blacklist.conf
### Настройка переадресации через протокол DoT на публичный DNS-сервер ###
# Настройка зоны переадресации:
forward-zone:
name: "." # Все доменные зоны и домены
forward-tls-upstream: yes # Использовать DNS-over-TLS
# Указывать домены через # после 853 порта обязательно!
# Адрес или адреса публичных DNS-серверов использующих протокол DoT:
# CloudFlare DNS
forward-addr: 1.1.1.1@853#one.one.one.one
forward-addr: 1.0.0.1@853#one.one.one.one
# Google DNS
#forward-addr: 8.8.8.8@853#dns.google
#forward-addr: 8.8.4.4@853#dns.google
# Wikimedia DNS
#forward-addr: 185.71.138.138@853#wikimedia-dns.org
Вносим необходимые изменения и сохраняем файл. На этом основная настройка DNS-сервера Unbound завершена.
4. Проверка корректности конфигурации Unbound
Проверяем корректность конфигурации
unbound-checkconf
Данная команда проверит основной файл конфигурации и другие, если они были добавлены. В случае присутствия ошибок, будут указаны строки в которых они находятся. Если ошибки отсутствуют, команда выведет следующие: unbound-checkconf: no errors in /etc/unbound/unbound.conf. После каждого изменения конфигурации рекомендуется использовать команду проверки.
5. Перезагрузка Unbound
Перезагружаем Unbound
systemctl restart unbound
Проверяем, что DNS-сервер Unbound работает, находится в автозагрузке и ошибок нет
systemctl status unbound

DNS-сервер Unbound успешно работает и находится в автозагрузке.
6. Проверка DNS-сервера Unbound
6.1. Проверка с сервера
На сервер где установлен Unbound выполняем DNS запрос через утилиту dig
dig @127.0.0.1 notby.net
- @127.0.0.1 – IP-адрес DNS-сервера, который необходимо использовать;
- notby.net – доменное имя, для которого происходит DNS запрос.

Как можно видеть, информация о DNS-записях домена успешно выведена.
6.2. Проверка работоспособности DNSSEC
Выполняем проверку
dig @127.0.0.1 sigfail.verteiltesysteme.net +dnssec | grep status
dig @127.0.0.1 dnssec-failed.org +dnssec | grep status
Это две команды обращаются к доменам в которых умышлено неверная подпись DNSSEC и вывод команды будет следующий:
- Если в параметре status значение SERVFAIL, то DNS-сервер выполнил проверку DNSSEC и отбросил неверную подпись;
- Если в параметре status значение NOERROR, то DNS-сервер пропустил неверную подпись и значит DNSSEC не работает.
Выполняем проверку наличия флага ad
dig @127.0.0.1 sigok.verteiltesysteme.net +dnssec | grep flags
dig @127.0.0.1 dnssec-tools.org +dnssec | grep flags
Флаг ad означает, что Unbound передает данный флаг, ответ был проверен и подписи DNSSEC действительны.
6.3. Проверка с устройств локальной сети
Теперь необходимо проверить что DNS-сервер доступен и отвечает на запросы компьютеров локальной или Wi-Fi сети.
В операционной системе Linux выполняем аналогичный DNS запрос через утилиту dig, но указав IP-адрес (192.168.0.1 в моем случае) DNS-сервера в локальной сети.
dig @192.168.0.1 notby.net

Время ответа DNS-сервера составило менее чем 1 мс, так как записи домена уже были кэшированы.
В операционной системе Windows выполняем DNS запрос через утилиту nslookup
nslookup notby.net 192.168.0.1
При работе через nslookup адрес DNS-сервера необходимо писать в самом конце.
7. Настройка DNS клиента в Linux
Теперь необходимо настроить параметры сети сервера, чтобы он использовал Unbound в качестве локального DNS-сервера.
Открываем файл настройки DNS клиента
nano /etc/resolv.conf
Изменяем значение параметра nameserver на 127.0.0.1 и добавляем options trust-ad
nameserver 127.0.0.1
options trust-ad
Запрещаем изменение файла /etc/resolv.conf на случай, если какая-то утилита (DHCP клиент, Network Manager, WireGuard) захочет его перезаписать
chattr +i /etc/resolv.conf
Проверяем что сервер начал использовать локальный DNS-сервер Unbound
dig | grep SERVER
В результате выполнения данной команды должен выведен IP-адрес 127.0.0.1 используемого DNS-сервера
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
Аналогично настраиваем устройства локальной сети или Wi-Fi, но в качестве DNS-сервера указываем IP-адрес Unbound.
Если в локальной сети используется DHCP сервер, то изменяем его настройки, чтобы он выдавал IP-адрес DNS-сервера Unbound.
Читай как настроить DCHP сервер: Установка и настройка Kea DHCP-сервер в Debian / Ubuntu, Настройка DHCP-сервера ISC-DHCP в FreeBSD
8. Запрет доступа к любым DNS-серверам по 53 порту
Для повышения безопасности, анонимности сервера и устройств локальной и Wi-Fi сети можно полностью запретить доступ к любым внешним DNS-серверам по открытому незащищенному каналу, то есть заблокировать любой исходящий трафик по 53 порту.
В качестве файрвола и маршрутизатора у меня на сервере используется UFW, поэтому пример запрета будет показан на основе него.
Читай как настраивать файрвол UFW: Утилита UFW для настройки и конфигурации файрвола в Linux
Запрещаем подключение к любым DNS-серверам по незащищённому протоколу
ufw deny out any 53
Проверяем что доступ к DNS-серверу Unbound есть с компьютеров локальной сети и самого сервера
dig notby.net

Проверяем что доступ отсутствует к любому другому DNS-серверу (например 1.1.1.1) по открытому протоколу
dig @1.1.1.1 notby.net

Как можно видеть, доступ к внешнему DNS-серверу по 53 порту получить не удалось.
9. Черный список доменов (блокировка рекламы)
Unbound может блокировать выборочно домены или целые доменные зоны. Это может быть полезно если необходимо закрыть доступ до определенных сайтов или заблокировать рекламные домены.
9.1. Файл blacklist.conf
Для удобства создаем отдельный файл blacklist.conf в каталоге /etc/unbound/
touch /etc/unbound/blacklist.conf
Открываем файл blacklist.conf
nano /etc/unbound/blacklist.conf
Например, заблокируем домен example.com и example.net. Для этого добавляем строки:
local-zone: "example.com" always_refuse
local-zone: "example.net" always_refuse
Параметр always_refuse означает, что DNS-сервер всегда будет отказывать на запросы IP-адреса домена и другие.
Для каждого домена который нужно заблокировать, необходимо использовать отдельную строку.
Вносим необходимый список доменов, которые необходимо заблокировать и сохраняем файл.
9.2. Подключение файла blacklist.conf
Открываем основной конфигурационный файл unbound.conf
nano /etc/unbound/unbound.conf
Добавляем строку или раскомментируем её, если использовался конфигурационный файл с данной статьи
include: /etc/unbound/blacklist.conf
Обязательно подключать файл blacklist.conf в разделе server: конфигурационного файла unbound.conf
Очищаем кеш и перезагружаем настройки Unbound
systemctl reload unbound
9.3. Проверка заблокированного домена
Выполняем DNS запрос к заблокированному домену
dig @127.0.0.1 example.com +noall +answer
- @127.0.0.1 – IP-адрес DNS-сервера Unbound;
- example.com – доменное имя, для которого происходит DNS запрос;
- +noall +answer – показывать в выводе только IP-адреса для домена.
При правильной настройке, вывод для команды выше будет пустой. То есть не одной DNS-записи для данного домена.
9.4. Блокировка рекламы (конвертация hosts файла)
Различные сервисы по блокировке рекламы довольно часто основываются на списке рекламных доменов. Блокировка происходит на уровне доменов. Эти списки в формате hosts файла без проблем можно скачать в интернете и они имеют следующий вид:
0.0.0.0 ads-banner.com
0.0.0.0 ads.banner.net
0.0.0.0 advertise.com
Скачиваем hosts файл со списком заблокированных доменов в удобное место.
Выполняем конвертацию hosts файла в формат DNS-сервера Unbound
grep '^0\.0\.0\.0' /tmp/ads_hosts | awk '{print "local-zone: \""$2"\" always_refuse"}' > /etc/unbound/blacklist.conf
- /tmp/ads_hosts – путь до скачанного hosts файла;
- /etc/unbound/blacklist.conf – путь до файла blacklist.conf ранее созданного.
Обрати внимание, что данная команда полностью перезапишет файл blacklist.conf и удалит ранее добавленные домены. Если это недопустимо, используй разные имена файлов.
После выполнения конвертации, перезагружаем настройки DNS-сервера Unbound и проверяем, что реклама пропала…
systemctl reload unbound