notby.NET Logo

Собственный 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
Установка Unbound DNS-сервер в операционную систему Debian через консольную команду: 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
В терминале Debian выполнена команда “systemctl status unbound”. DNS-сервер 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-сервера 127.0.0.1 (localhost) командой “dig @127.0.0.1 notby.net +nocmd +nocomments” в консоли Debian сервера. Получен успешный ответ DNS-сервера и отображена информация об DNS зоне домена notby.net

Как можно видеть, информация о 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 командой “dig @192.168.0.1 notby.net +nocmd +nocomments” в консоли Debian для домена notby.net через DNS-сервер локальной сети. Успешный ответ DNS-сервера, отображены записи A для домена, а время ответа DNS составляет 0 миллисекунд

Время ответа 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 запись для домена notby.net через локальный DNS-сервер успешно получена командой “dig notby.net +nocmd +nocomments” в терминале Debian

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

dig @1.1.1.1 notby.net
В терминале Debian выполнена команда “dig @1.1.1.1 notby.net”. Получение DNS запись для домена notby.net через сервер DNS-сервер 1.1.1.1 закончилось ошибкой: no servers could be reached

Как можно видеть, доступ к внешнему 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