PowerDNS — авторитативный DNS-сервер, который хранит зоны не в текстовых файлах, а в базе данных. Это упрощает автоматизацию, выдачу зон через API и работу с сотнями доменов. Разберём установку с PostgreSQL, создание зоны, DNSSEC, вторичные серверы и диагностику.
Авторитативный, а не рекурсивный
Авторитативный сервер отвечает за конкретные домены и не должен обслуживать произвольные запросы из интернета. PowerDNS Recursor — отдельный продукт для кэширования и рекурсии. Если включить рекурсию на авторитативном сервере, его быстро используют для amplification-атак. Поэтому в конфигурации ниже рекурсия не включается, а порт 53 открыт только для нужных сетей.
Важно: авторитативный сервер не кэширует ответы и не заменяет рекурсивный резолвер. Клиенты обращаются к нему за зонами, а за внешними именами — к резолверу.
Бэкенд gpgsql хранит записи в PostgreSQL. Альтернативы — MySQL, SQLite и LMDB; для небольшой домашней зоны хватит SQLite, для нескольких серверов и автоматизации удобнее PostgreSQL.
Установка и база
Ставим сервер и бэкенд, затем создаём отдельного пользователя и базу. Схему берём из пакета, а не пишем вручную: она содержит нужные таблицы и индексы.
sudo apt update && sudo apt install -y pdns-server pdns-backend-pgsql
sudo -u postgres createuser --no-createdb --no-createrole pdns
sudo -u postgres createdb -O pdns pdns
sudo -u postgres psql -d pdns -f /usr/share/pdns-backend-pgsql/schema/schema.pgsql.sql
sudo -u postgres psql -c "ALTER USER pdns WITH PASSWORD 'change-me';"
Пароль из примера замените своим и храните в менеджере секретов. Файл pdns.conf с паролем доступен только root и группе pdns.
Конфигурация pdns.conf
Минимальный набор — бэкенд, доступ к базе и API на localhost. gpgsql-dnssec=yes нужен для хранения ключей DNSSEC в той же базе.
launch=gpgsql
gpgsql-host=127.0.0.1
gpgsql-port=5432
gpgsql-dbname=pdns
gpgsql-user=pdns
gpgsql-password=change-me
gpgsql-sslmode=prefer
gpgsql-dnssec=yes
dnssec-key-cache-ttl=3600
api=yes
api-key=Zx9Qm2Lp7Rt4Vw8Yb3Nc6Kd1Hf5Js0
webserver=yes
webserver-address=127.0.0.1
webserver-port=8081
webserver-allow-from=127.0.0.1,192.168.10.0/24,::1
После правки проверьте синтаксис запуском вручную: pdns_server --daemon=no --guardian=no --loglevel=9. В продакшене перезапустите службу через systemctl restart pdns и смотрите журнал.
Зоны и записи через pdnsutil
pdnsutil работает напрямую с бэкендом и не требует API. Зона создаётся с именем первичного NS, далее добавляются записи. После ручных изменений поднимите serial, иначе вторичные серверы не заметят обновление.
pdnsutil create-zone example.com ns1.example.com
pdnsutil add-record example.com www A 3600 192.0.2.10
pdnsutil add-record example.com @ MX 3600 "10 mail.example.com."
pdnsutil add-record example.com @ TXT 3600 "v=spf1 mx -all"
pdnsutil check-zone example.com
pdnsutil increase-serial example.com
Для CNAME помните: он не может сосуществовать с другими записями того же имени. Для сервисов используйте SRV, для подтверждения домена — TXT. Проверка check-zone ловит отсутствующий SOA, конфликты CNAME и ошибки в NS.
TTL выбирайте по частоте изменений: для стабильных A-записей подойдут часы, для переездов — минуты. Слишком маленький TTL увеличивает нагрузку и трафик, слишком большой задерживает исправления.
DNSSEC
PowerDNS подписывает зону онлайн. Ключи хранятся в базе, а DS-запись нужно передать регистратору. Не включайте DNSSEC, пока не понимаете, как обновлять DS при смене ключей: ошибка делает домен нерезолвящимся.
pdnsutil secure-zone example.com
pdnsutil show-zone example.com
pdnsutil export-zone-ds example.com
pdnsutil rectify-zone example.com
rectify-zone пересчитывает порядок записей для корректной подписи. После включения проверьте ответы с флагом +dnssec и валидацию на внешнем резолвере.
HTTP API
API включён на localhost и защищён ключом в заголовке X-API-Key. Через него удобно создавать зоны из панели или CI. Ключ должен быть случайным. Не выставляйте API в интернет без reverse proxy, TLS и ограничения по IP.
export PDNS_KEY="Zx9Qm2Lp7Rt4Vw8Yb3Nc6Kd1Hf5Js0"
curl -s -H "X-API-Key: $PDNS_KEY" http://127.0.0.1:8081/api/v1/servers/localhost/zones
curl -s -X POST -H "X-API-Key: $PDNS_KEY" -H "Content-Type: application/json" --data @zone.json http://127.0.0.1:8081/api/v1/servers/localhost/zones
В zone.json укажите name, kind и nameservers; записи передаются массивом rrsets. После изменения через API PowerDNS обновит serial; поведение задают метаданные SOA-EDIT-API.
{
"name": "example.com.",
"kind": "Native",
"nameservers": ["ns1.example.com."]
}
Вторичные серверы
Для отказоустойчивости поднимите второй PowerDNS и настройте передачу зон. На основном узле разрешите AXFR только доверенным адресам, на вторичном включите режим secondary.
# основной
primary=yes
allow-axfr-ips=127.0.0.1,192.168.10.0/24,::1
also-notify=192.168.10.12
# вторичный
secondary=yes
autosecondary=yes
Старые имена master и slave принимаются, но в новых конфигурациях используйте primary/secondary. Для защиты настройте TSIG: pdnsutil generate-tsig-key axfr-key hmac-sha256 и метаданные TSIG-ALLOW-AXFR.
Диагностика
Проверяйте ответы напрямую, минуя кэш. +norecurse показывает, что отдаёт авторитативный сервер, а pdns_control — состояние зон.
dig @127.0.0.1 example.com SOA +short
dig @127.0.0.1 www.example.com A +norecurse
dig @127.0.0.1 example.com AXFR
pdns_control list-zones
pdnsutil list-all-zones
journalctl -u pdns -f
Если зона не отвечает, проверьте launch, доступ к базе и pdnsutil check-zone. Если отвечает старыми данными — кэш резолвера, TTL или не поднятый serial. Для вторичного сервера смотрите pdns_control show example.com и журнал передач.
Чек-лист
- Рекурсия на авторитативном сервере выключена.
- База и pdns.conf доступны только нужным пользователям.
- API слушает localhost и закрыт ключом.
- AXFR ограничен по IP или TSIG.
- DNSSEC и DS проверены на внешнем резолвере.
Итог
PowerDNS с PostgreSQL даёт управляемый DNS: зоны лежат в базе, изменения автоматизируются через API, а вторичные серверы забирают копии по AXFR. Главное — не включать рекурсию, беречь ключи и проверять каждую зону через dig и check-zone. Для домашней сети достаточно SQLite, для инфраструктуры — PostgreSQL и резервирование.