· 16 мин чтения

Связка BIND и PowerDNS: корпоративный DNS, который переживёт любой сбой

Семёнов Евгений Сергеевич, директор АйТи Фреш. DNS — невидимая основа всей сетевой инфраструктуры. Когда он падает или отдаёт неправильные ответы, ломается всё сразу: почта, сайты, VPN, сервисы. У нас на практике я всегда разношу DNS на два разных движка — BIND и PowerDNS — именно ради защиты от уязвимостей: когда выйдет очередной CVE на одну реализацию, вторая продолжит работать. Разберём, как собрать такую архитектуру из коробки за два рабочих дня.

Зачем мешать два движка

Стандартная схема — master + два slave — уязвима к багам в самом софте. BIND и PowerDNS — разные кодовые базы, написанные разными командами, на разных языках. Совмещая, вы получаете:

Целевая схема

Типовая инфраструктура, которую я разворачиваю:

РольДвижокГде стоит
Master авторитативныйBIND9Офис HQ, за файрволом
Slave авторитативныйPowerDNSDMZ, открытый в интернет
Slave авторитативный #2BIND9Второй офис
Рекурсор для офисаUnbound или BINDВнутри корпоративной сети

Установка BIND9 как master

apt update
apt install -y bind9 bind9utils dnsutils

# /etc/bind/named.conf.options
options {
    directory "/var/cache/bind";
    recursion no;
    allow-query { any; };
    allow-transfer { key "powerdns-tsig"; };
    also-notify { 192.0.2.20; };   # PowerDNS slave
    notify yes;

    listen-on { 192.0.2.10; 127.0.0.1; };
    listen-on-v6 { none; };
};

# TSIG-ключ для безопасной репликации
key "powerdns-tsig" {
    algorithm hmac-sha256;
    secret "сгенерированный_base64_ключ";
};

Генерация TSIG-ключа:

tsig-keygen -a hmac-sha256 powerdns-tsig

Описание зоны в BIND

# /etc/bind/named.conf.local
zone "corp.example.ru" {
    type master;
    file "/etc/bind/zones/db.corp.example.ru";
    allow-transfer { key "powerdns-tsig"; };
    also-notify { 192.0.2.20 key "powerdns-tsig"; };
};

# /etc/bind/zones/db.corp.example.ru
$TTL 3600
@   IN  SOA ns1.corp.example.ru. hostmaster.corp.example.ru. (
        2025080801  ; serial
        3600        ; refresh
        900         ; retry
        1209600     ; expire
        300         ; minimum
)
    IN  NS  ns1.corp.example.ru.
    IN  NS  ns2.corp.example.ru.
ns1 IN  A   192.0.2.10
ns2 IN  A   192.0.2.20
www IN  A   192.0.2.100
mx01 IN A   192.0.2.50
@   IN  MX 10 mx01.corp.example.ru.
named-checkconf
named-checkzone corp.example.ru /etc/bind/zones/db.corp.example.ru
systemctl restart bind9

Установка PowerDNS как slave

apt install -y pdns-server pdns-backend-mysql mariadb-server

# Инициализация схемы БД
mysql -e "CREATE DATABASE pdns CHARACTER SET utf8mb4"
mysql -e "CREATE USER 'pdns'@'localhost' IDENTIFIED BY 'strongpass'"
mysql -e "GRANT ALL ON pdns.* TO 'pdns'@'localhost'"
mysql pdns < /usr/share/pdns-backend-mysql/schema/schema.mysql.sql

# /etc/powerdns/pdns.conf
launch=gmysql
gmysql-host=127.0.0.1
gmysql-user=pdns
gmysql-password=strongpass
gmysql-dbname=pdns
slave=yes
master=no
allow-notify-from=192.0.2.10/32
local-address=192.0.2.20
api=yes
api-key=REST_API_KEY
webserver=yes
webserver-port=8081

systemctl restart pdns

Регистрация зоны-slave в PowerDNS

# Через pdnsutil
pdnsutil create-slave-zone corp.example.ru 192.0.2.10

# Добавление TSIG-ключа
pdnsutil import-tsig-key powerdns-tsig hmac-sha256 'сгенерированный_base64_ключ'
pdnsutil activate-tsig-key corp.example.ru powerdns-tsig slave

# Принудительный AXFR
pdns_control retrieve corp.example.ru

Через 30 секунд проверяем:

dig @192.0.2.20 corp.example.ru SOA
dig @192.0.2.20 www.corp.example.ru A

DNSSEC на авторитативных

DNSSEC включаем на master и slaves с одним набором ключей. В BIND9:

# Добавляем в zone-блок
zone "corp.example.ru" {
    ...
    inline-signing yes;
    auto-dnssec maintain;
    key-directory "/etc/bind/keys";
};

# Генерация ключей
cd /etc/bind/keys
dnssec-keygen -K . -a RSASHA256 -b 2048 -n ZONE corp.example.ru
dnssec-keygen -K . -a RSASHA256 -b 4096 -f KSK -n ZONE corp.example.ru
chown -R bind:bind /etc/bind/keys
chmod 600 /etc/bind/keys/*
rndc reload corp.example.ru

PowerDNS получает подписанную зону через AXFR и отдаёт клиентам уже с RRSIG-записями. Отдельная настройка подписи на slave не нужна.

Split-horizon (views) для внутренних и внешних клиентов

# BIND с двумя views
acl "internal" { 10.0.0.0/8; 192.168.0.0/16; };
acl "external" { any; };

view "internal" {
    match-clients { internal; };
    recursion yes;
    zone "corp.example.ru" {
        type master;
        file "/etc/bind/zones/corp.example.ru-internal";
    };
};

view "external" {
    match-clients { external; };
    recursion no;
    zone "corp.example.ru" {
        type master;
        file "/etc/bind/zones/corp.example.ru-external";
    };
};

В internal-зоне пишем внутренние IP (10.x), в external — публичные. Для PowerDNS аналогичную схему даёт Lua-бэкенд с geoip или простым if/else по адресу клиента.

Реальный кейс: DNS на 5 площадок

В январе 2025 пришёл клиент — холдинг с 5 площадками в ЦФО (Москва HQ, производство в Подольске, 3 филиала в регионах). Старый DNS — два BIND на одной площадке, при падении канала в HQ падал весь холдинг. Задача — географически распределённый DNS с репликацией, защита от CVE, split-horizon для внутренних и публичных зон.

Что внедрили за 4 рабочих дня:

  1. Master BIND9 в HQ на нашем Dell Xeon Platinum 8280, изолированный от интернета.
  2. Slave PowerDNS в DMZ HQ, открытый 53/udp и 53/tcp.
  3. Slave BIND9 в дата-центре МТС Москва (наша инфраструктура).
  4. По одному slave PowerDNS в каждом из 3 филиалов (Linux-виртуалки 2 vCPU / 2 ГБ RAM).
  5. TSIG-аутентификация для всех AXFR/IXFR, DNSSEC на публичных зонах.
  6. Split-horizon: внутренние зоны отдаются с внутренних IP, публичные — с внешних.
  7. Мониторинг здоровья всех 7 серверов через Prometheus blackbox-exporter, алерты в Telegram.

Стоимость проекта 148 000 руб. Через месяц в Подольске упал интернет на 6 часов — внутренние сервисы продолжали работать на локальном slave, внешние резолвы получали ответы от PowerDNS в DMZ HQ. Клиент не заметил.

Мониторинг и эксплуатация

# Проверка зоны с разных серверов
for ns in 192.0.2.10 192.0.2.20 10.1.1.53 10.2.1.53 10.3.1.53; do
  echo "=== $ns ==="
  dig @$ns corp.example.ru SOA +short
done

# Serial должен совпадать везде — иначе репликация сломана

# Prometheus-метрики PowerDNS
pdns_control get-all | head -30

# BIND stats-channels на порту 8053
curl http://127.0.0.1:8053/xml/v3/server | xmllint --format -

Практические советы

Поднимем отказоустойчивый DNS для вашей инфраструктуры

Проектирую и внедряю корпоративный DNS на BIND+PowerDNS: master-slave, DNSSEC, split-horizon, мониторинг. В АйТи Фреш 15+ лет в сетевой инфраструктуре, свои 8 серверов в дата-центре МТС Москва с 40G Mellanox. Базовая схема на 3 сервера — 1 рабочая неделя, стоимость от 75 000 руб.

Телефон: +7 903 729-62-41
Telegram: @ITfresh_Boss
Семёнов Евгений Сергеевич, директор АйТи Фреш

FAQ — частые вопросы о BIND и PowerDNS

Зачем использовать два разных движка DNS?
Страховка от уязвимостей: когда выходит CVE на BIND, атакованными оказываются только серверы на BIND, PowerDNS продолжает работать.
BIND и PowerDNS совместимы по протоколу?
Да, оба поддерживают стандартный AXFR/IXFR. BIND может быть master для PowerDNS-slave и наоборот с использованием TSIG.
Как управлять зонами PowerDNS?
Через REST API (порт 8081) или PowerDNS-Admin. Зоны хранятся в БД, управление удобнее чем в файлах BIND.
DNSSEC — нужен ли в корпоративной сети?
Для публичных зон обязателен. Для внутренних — по желанию: в крупных компаниях включают для защиты от spoofing внутри сети.
Как сделать failover между площадками?
DNS round-robin с короткими TTL и скриптом обновления, или GeoDNS через PowerDNS Lua-бэкенд.

Подпишитесь на рассылку ITfresh

Раз в неделю — практические гайды для руководителя IT и сисадмина: безопасность, 1С, миграции, резервные копии, лайфхаки из реальных проектов.

Реквизиты оператора персональных данных

ООО «АЙТИ-ФРЕШ», ИНН 7719418495, КПП 771901001. Юридический адрес: 105523, г. Москва, Щёлковское шоссе, д. 92, корп. 7. Контакт: info@itfresh.ru, +7 903 729-62-41. Оператор обрабатывает e-mail подписчика в целях рассылки информационных и рекламных материалов до момента отзыва согласия.