Блог

Свой DNS-резолвер: зачем, какой выбрать и как настроить Unbound за 10 минут.

dns_reslolver
Linux

Свой DNS-резолвер: зачем, какой выбрать и как настроить Unbound за 10 минут.

Каждый раз когда ваш сервер обновляет пакеты, проверяет сертификат, коннектится к внешнему API или отправляет метрики в мониторинг — он резолвит домен. И этот запрос уходит на 1.1.1.1 или 8.8.8.8. Cloudflare видит что ваш сервер в 3 ночи полез на репозиторий пакетов, потом на API платёжной системы, потом на базу данных угроз. Полная картина вашей инфраструктуры — без взлома, просто из DNS-логов.

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

ЗАЧЕМ СВОЙ РЕЗОЛВЕР

Приватность — самая очевидная причина. Внешний DNS-провайдер видит каждый домен к которому обращается сервер. Это не паранойя — это реальные данные которые собираются, анализируются и могут утекать. Свой резолвер оставляет эту информацию у вас.

Независимость — менее очевидная но более критичная. 1.1.1.1 надёжный, но это чужой сервер. В октябре 2021 упали DNS серверы Facebook — и всё что зависело от них перестало работать. 1.1.1.1 в тот день работал, но завтра может не повезти именно вашему провайдеру. Свой резолвер ходит напрямую к корневым серверам и не зависит ни от кого.

Как это работает: корневые серверы — это вершина DNS-иерархии. Их 13 групп, они всегда доступны и знают где искать любой домен. Обычный резолвер типа 1.1.1.1 сам ходит к ним и кэширует ответы — вы пользуетесь его кэшем. Свой резолвер делает то же самое, но для вас лично — и ни от чьего кэша не зависит.

Скорость — приятный бонус. Часто запрашиваемые домены оседают в локальном кэше. npm registry, GitHub, Docker Hub — всё это резолвируется за единицы миллисекунд без выхода в интернет.

Контроль — то что открывает новые возможности. Хотите заблокировать конкретный домен на уровне DNS? Добавить внутренние записи для локальной сети? Логировать все DNS-запросы сервера для аудита? Со своим резолвером это делается в конфиге.

Блокировка доменов через local-zone — одна из самых простых и полезных возможностей. Добавьте в конфиг:

server:
    # Заблокировать домен — вернуть REFUSED
    local-zone: "example.com" refuse

    # Заблокировать рекламные сети
    local-zone: "doubleclick.net" refuse
    local-zone: "googlesyndication.com" refuse

    # Перенаправить на свой IP (для внутренних сервисов)
    local-zone: "internal.example.com" static
    local-data: "internal.example.com A 10.0.0.5"

refuse — резолвер вернёт REFUSED, браузер покажет ошибку DNS. static с local-data — вернёт указанный IP вместо реального. Это удобно для внутренних сервисов которые должны резолвиться в приватный IP.

ТРИ ВАРИАНТА: UNBOUND, BIND, POWERDNS

Выбор резолвера зависит от задачи. Все три решают разные проблемы.

Unbound — специализированный кэширующий резолвер. Не пытается делать всё сразу: он принимает запросы, ищет ответы у корневых серверов, кэширует результат, проверяет DNSSEC. Настраивается за 10 минут, потребление памяти зависит от размера кэша — при конфигурации в этой статье около 150-200 МБ, работает стабильно годами без вмешательства. Если нужен локальный резолвер для сервера или небольшой сети — это правильный выбор.

Bind (named) — промышленный стандарт существующий с 1980-х. Стоит за большей частью DNS-инфраструктуры в мире. Умеет быть одновременно кэширующим резолвером и авторитетным сервером для ваших доменов. Поддерживает GeoDNS — разные ответы для пользователей из разных стран. Умеет split-horizon — разные ответы для внутренней и внешней сети. Мощный инструмент с соответствующей кривой обучения.

PowerDNS — современный вариант для тех кто хочет управлять DNS программно. Зоны хранятся в MySQL или PostgreSQL, записи управляются через REST API. Можно написать скрипт который автоматически создаёт DNS-записи при запуске нового сервера. Выбор для автоматизированных систем и тех кто не хочет редактировать текстовые файлы руками.

Для локального резолвера на одном сервере — Unbound. Для полноценного DNS-сервера с зонами — Bind. Для динамического управления через API — PowerDNS.

UNBOUND: УСТАНОВКА И НАСТРОЙКА

Установка занимает одну команду:

apt install unbound          # Debian/Ubuntu
dnf install unbound          # RHEL/Fedora

После установки Unbound слушает на 127.0.0.1:53 и готов принимать запросы. Но базовая конфигурация требует нескольких правок.

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

nano /etc/unbound/unbound.conf

Минимальная рабочая конфигурация:

server:
    # Слушаем только на localhost
    interface: 127.0.0.1
    port: 53

    # Разрешаем запросы только с локального хоста
    access-control: 127.0.0.1/32 allow
    access-control: 0.0.0.0/0 refuse

    # DNSSEC
    auto-trust-anchor-file: "/var/lib/unbound/root.key"

    # Скрываем версию и идентификатор
    hide-version: yes
    hide-identity: yes

    # Кэш
    cache-min-ttl: 300
    cache-max-ttl: 86400
    msg-cache-size: 50m
    rrset-cache-size: 100m

    # Производительность
    num-threads: 2
    so-reuseport: yes

    # Логирование
    verbosity: 1
    log-queries: no

Скачайте корневые якоря DNSSEC:

unbound-anchor -a /var/lib/unbound/root.key

Проверьте конфигурацию и запустите:

unbound-checkconf
systemctl enable --now unbound

Проверка что работает:

dig @127.0.0.1 cloudflare.com
dig @127.0.0.1 cloudflare.com +dnssec

Второй запрос с +dnssec должен вернуть записи с флагом ad (authenticated data) — значит DNSSEC проверка прошла.

ПОДКЛЮЧЕНИЕ К СИСТЕМНОМУ РЕЗОЛВЕРУ

Unbound запущен, но сервер его ещё не использует — systemd-resolved по-прежнему отправляет запросы на 1.1.1.1. Нужно переключить системный DNS на 127.0.0.1.

Важный момент: DNSSEC и DoT в systemd-resolved нужно отключить. Если оставить их включёнными — systemd-resolved будет пытаться сам валидировать DNSSEC и шифровать запросы поверх того что уже делает Unbound. Двойная работа, и хуже — конфликт настроек. Unbound сам занимается всем этим, systemd-resolved здесь просто передатчик.

# /etc/systemd/resolved.conf
[Resolve]
DNS=127.0.0.1
DNSOverTLS=no
DNSSEC=no
systemctl restart systemd-resolved
resolvectl status | grep "Current DNS Server"

Должно показать 127.0.0.1. Если видите 1.1.1.1 или Hetzner IP — что-то пошло не так, проверьте netplan или /etc/resolv.conf.

Проверка что резолвинг идёт через Unbound:

resolvectl query cloudflare.com

DOT UPSTREAM: ШИФРУЕМ ИСХОДЯЩИЕ ЗАПРОСЫ

Локальный резолвер решает проблему внутри сервера — запросы не уходят на чужой резолвер. Но когда Unbound не находит ответ в кэше, он всё равно идёт к внешним серверам — форвардерам. Этот исходящий трафик по умолчанию идёт открытым текстом по UDP на порт 53. То есть провайдер по-прежнему видит какие домены резолвирует ваш сервер — просто теперь не постоянно, а только при промахе кэша.

DoT upstream шифрует именно эти исходящие запросы. Провайдер видит зашифрованный трафик на порт 853 — но не видит какие домены вы резолвируете.

Добавьте в конфигурацию:

forward-zone:
    name: "."
    forward-tls-upstream: yes
    forward-addr: 1.1.1.1@853#cloudflare-dns.com
    forward-addr: 8.8.8.8@853#dns.google
    forward-addr: 9.9.9.9@853#dns.quad9.net

Перезапустите:

systemctl restart unbound

Теперь Unbound кэширует локально, а запросы которые не нашлись в кэше шифрует через DoT и передаёт на форвардеры — 1.1.1.1, 8.8.8.8 или 9.9.9.9. Провайдер видит только зашифрованный трафик на порт 853.

ПРОВЕРКА И ОТЛАДКА

Статистика кэша:

unbound-control stats_noreset | grep -E "total|cache"

Сколько запросов обработано и какой процент из кэша — покажет насколько эффективно работает резолвер.

Тест DNSSEC:

# Этот домен должен вернуть SERVFAIL — он намеренно сломан для тестов
dig @127.0.0.1 dnssec-failed.org

# Этот должен резолвиться нормально
dig @127.0.0.1 cloudflare.com +dnssec

Если dnssec-failed.org возвращает SERVFAIL — DNSSEC валидация работает правильно.

Логи:

journalctl -u unbound -f

ИСПОЛЬЗОВАНИЕ СВОЕГО РЕЗОЛВЕРА С ДОМАШНЕГО КОМПА

Unbound в базовой конфигурации слушает только на 127.0.0.1 — доступен исключительно с самого сервера. Но его можно безопасно открыть для конкретного IP — например вашего домашнего компа. Тогда в настройках сети на компе вместо 8.8.8.8 прописываете IP своего сервера, и весь DNS-трафик идёт через ваш резолвер.

Узнайте свой домашний IP:

curl ifconfig.me

Откройте Unbound для этого IP — добавьте в конфиг:

server:
    interface: 0.0.0.0
    access-control: 0.0.0.0/0 refuse
    access-control: 127.0.0.1/32 allow
    access-control: ВАШ_ДОМАШНИЙ_IP/32 allow

Откройте порт 53 в nftables только для вашего IP — никак иначе:

ip saddr ВАШ_ДОМАШНИЙ_IP udp dport 53 accept
ip saddr ВАШ_ДОМАШНИЙ_IP tcp dport 53 accept

Перезапустите Unbound:

systemctl restart unbound

Проверьте с домашнего компа что резолвер отвечает:

dig @IP_ВАШЕГО_СЕРВЕРА cloudflare.com

Если ответил — прописывайте IP сервера в настройках DNS сетевого адаптера на компе.

Важно: домашний IP обычно динамический — меняется при переподключении. Если IP изменился, резолвер перестанет отвечать. Придётся обновить правило в nftables и конфиг Unbound. Для постоянного использования лучше получить статический IP у провайдера или использовать Dynamic DNS.

КОГДА НУЖЕН BIND ИЛИ POWERDNS

Unbound — резолвер. Он не умеет быть авторитетным сервером для ваших доменов, не поддерживает зоны, не делает GeoDNS.

Если нужно размещать собственные DNS-зоны, настраивать split-horizon DNS, делать GeoDNS с разными ответами для разных стран, или строить полноценную DNS-инфраструктуру — это задача для Bind. Bind умеет быть одновременно и резолвером и авторитетным сервером, поддерживает сложные ACL и view-конфигурации для разделения внутренних и внешних зон.

PowerDNS выбирают когда DNS нужно администрировать программно: зоны хранятся в базе данных, записи управляются через REST API, можно написать собственный backend. Это выбор для автоматизированных систем и облачных провайдеров.

Детальная настройка Bind с практическими примерами — зоны, GeoDNS, split-horizon — разбирается в курсе по настройке DNS-сервера: два урока с полным погружением от базовой конфигурации до продвинутых возможностей.

ИТОГ

Свой резолвер — это не rocket science. Unbound ставится за пять минут, требует 150-200 МБ RAM при стандартной конфигурации кэша, и сразу даёт приватность, независимость от внешних провайдеров и локальное кэширование.

Для большинства серверов этого достаточно. Если задачи растут до уровня собственных зон и сложной маршрутизации DNS-трафика — следующий шаг это Bind.

Leave your thought here

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Поддержать автора

Если вам понравилась статья — вы можете поддержать автора.

Crypto donation button by NOWPayments