Выберите продукт

ACME DNS-01 wildcard через RFC2136: BIND update-policy и контроль propagation

Пошагово настраиваем выпуск wildcard-сертификатов по ACME DNS-01 через RFC2136 в BIND: создаём TSIG-ключ, даём минимум прав через update-policy только для _acme-challenge, проверяем nsupdate и dig на всех NS, разбираем propagation и типовые ошибки lego.
ACME DNS-01 wildcard через RFC2136: BIND update-policy и контроль propagation

Зачем DNS-01 и почему RFC2136 удобен для wildcard

Wildcard-сертификат (например, *.example.com) почти всегда означает проверку владения доменом через ACME DNS-01: CA ждёт, что в DNS появится специальная TXT-запись в _acme-challenge. HTTP-01 для wildcard не подходит, а DNS-01 подтверждает контроль над зоной на уровне DNS.

Если authoritative DNS у вас свой (BIND, hidden-master, собственная NS-инфраструктура) и вы не хотите зависеть от облачных API, самый прямой путь автоматизации — RFC2136 dynamic updates. ACME-клиент (например, lego) добавляет и удаляет TXT через аутентифицированный update (обычно TSIG), после чего ожидает, когда изменения станут видны тем NS, куда придёт проверка CA.

В этой схеме важны две вещи: безопасность (минимальные права в update-policy) и предсказуемый тайминг (понимание, где именно «застревает» propagation).

Как выглядит DNS-01 challenge на уровне записей

Для домена example.com ACME управляет записью:

_acme-challenge.example.com.  TXT  "<token>"

Wildcard не означает «запись на каждое имя». Challenge живёт в одной точке: _acme-challenge.example.com. Если вы заказываете сертификат сразу на example.com и *.example.com, клиент может создать один или несколько токенов (часто это несколько TXT на одном имени).

Если вы только планируете автоматизацию wildcard-сертификатов, полезно держать в голове ограничения DNS-01, гонки при параллельных запросах и типовые тайминги. В отдельной заметке я собрал практику: как автоматизировать wildcard через DNS-01.

Схема: master и secondary DNS, делегирование зоны и путь проверки TXT для ACME DNS-01

Предварительные условия: authoritative DNS и где CA будет проверять

Перед настройкой RFC2136 убедитесь, что вы управляете именно authoritative DNS для зоны, а не только рекурсивным резолвером. Минимально рабочая картина такая:

  • BIND является master (или hidden master) для example.com и принимает dynamic updates.
  • Если есть secondary NS, они забирают изменения через IXFR/AXFR (это напрямую влияет на задержки).
  • CA может прийти на любой NS из делегирования зоны, а не на тот сервер, который вы тестируете «по привычке».

Если зона обслуживается у внешнего DNS-провайдера и вы не можете включить RFC2136 на authoritative стороне, этот сценарий не применим: придётся использовать API провайдера или выносить challenge в отдельную зону, где у вас есть управление.

FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

TSIG для RFC2136: создаём ключ и подключаем в named

RFC2136 без TSIG почти всегда заканчивается небезопасной конфигурацией. Делайте обновления только с TSIG и храните секрет как обычный production-секрет (минимум доступов, ротация при подозрении на компрометацию). Для современного BIND выбирайте hmac-sha256, если нет требований совместимости.

tsig-keygen -a hmac-sha256 acme-rfc2136 > /etc/bind/keys/acme-rfc2136.key

Содержимое файла будет выглядеть примерно так:

key "acme-rfc2136" {
  algorithm hmac-sha256;
  secret "BASE64SECRET==";
};

Подключите ключ в конфигурацию named (удобнее через отдельный файл и include):

include "/etc/bind/keys/acme-rfc2136.key";

Ограничьте права на файл ключа так, чтобы его мог читать только пользователь/группа BIND:

chown root:bind /etc/bind/keys/acme-rfc2136.key
chmod 640 /etc/bind/keys/acme-rfc2136.key

BIND update-policy: минимальные привилегии для _acme-challenge

Самая распространённая ошибка — разрешить ключу обновлять всю зону. Это превращает утечку TSIG в полный захват DNS. Для ACME обычно достаточно разрешить изменения только TXT в строго заданной точке _acme-challenge.

Пример для зоны example.com:

zone "example.com" {
  type master;
  file "/var/lib/bind/zones/db.example.com";

  update-policy {
    grant acme-rfc2136 name _acme-challenge.example.com. txt;
  };
};

Что важно проверить в этом фрагменте:

  • Права выданы на конкретное имя и тип: только txt и только _acme-challenge.example.com.
  • Точка в конце FQDN обязательна, чтобы не получить относительное имя и неожиданные совпадения.
  • Если зон несколько, безопаснее иметь отдельный TSIG на зону или, как минимум, отдельные grant под каждую зону.

Динамическая зона и файлы .jnl: что считается нормой

После включения dynamic updates BIND обычно создаёт рядом с файлом зоны журналы (например, .jnl). Это нормально: изменения фиксируются в журнале и затем применяются к зоне. Не редактируйте файл зоны вручную при активных обновлениях: легко получить рассинхрон и откаты. Для ручных правок используйте управляемый процесс (freeze/thaw) или вносите изменения через nsupdate.

Проверяем RFC2136 вручную через nsupdate (до интеграции с ACME)

До того как подключать lego или любой другой ACME-клиент, отладьте базовую цепочку: TSIG корректен, правило update-policy подходит, BIND принимает обновление именно в нужную зону/view.

Запустите nsupdate с вашим ключом:

nsupdate -k /etc/bind/keys/acme-rfc2136.key

Далее в интерактивном режиме:

server ns1.example.com
zone example.com
update add _acme-challenge.example.com. 60 TXT "test-token"
send

Проверьте authoritative-ответ прямо на NS:

dig @ns1.example.com _acme-challenge.example.com TXT +noall +answer

После проверки удалите тестовую запись:

nsupdate -k /etc/bind/keys/acme-rfc2136.key
server ns1.example.com
zone example.com
update delete _acme-challenge.example.com. TXT
send

Настройка lego для RFC2136: что учесть для wildcard

На практике lego часто используют в CI/CD, контейнерах и systemd-таймерах. Общая логика для RFC2136 всегда одна: lego должен уметь подписывать dynamic update вашим TSIG и отправлять его на authoritative DNS (обычно master или hidden master).

Обычно требуется указать такие параметры (конкретные имена переменных зависят от способа запуска и версии):

  • DNS-сервер, куда отправлять update (желательно master/hidden master);
  • имя TSIG-ключа;
  • алгоритм TSIG;
  • секрет TSIG;
  • время ожидания перед проверкой (delay/timeout для propagation).

Практический подход: update отправляйте на master, а проверку TXT делайте по всем NS из делегирования — так вы заранее увидите, что CA тоже увидит запись.

Propagation: почему CA «не видит» TXT, хотя запись уже добавлена

Propagation в DNS-01 — это не только «подождать TTL». На wildcard через RFC2136 чаще всего встречаются три вида задержек:

  • задержка репликации master → secondary (IXFR/NOTIFY/ACL/TSIG между NS);
  • кэширование у резолверов (включая негативный кэш после NXDOMAIN);
  • проверка CA у другого NS, чем тот, на котором вы «увидели» запись.

Для успешной валидации важно не то, что TXT виден «у вас», а то, что TXT виден на authoritative NS из делегирования зоны, потому что CA пойдёт именно туда.

Мини-чек диагностики: где именно тормозит

1) Проверка master:

dig @ns1.example.com _acme-challenge.example.com TXT +noall +answer

2) Проверка каждого NS из делегирования (особенно secondary):

dig @ns2.example.com _acme-challenge.example.com TXT +noall +answer

3) Проверка SOA serial на secondary (быстрый признак, что зона обновилась):

dig @ns2.example.com example.com SOA +noall +answer

Если serial на secondary не меняется, проблема обычно не в кэше, а в репликации (transfer/notify/ACL). Если же serial обновился, но где-то TXT не виден, смотрите views/split-horizon и то, какой view отвечает на публичные запросы. Если вы используете views, пригодится разбор типовых ошибок: как настроить BIND views (split-horizon) без сюрпризов.

TTL и negative caching: почему 60 секунд не всегда 60

Низкий TTL (например, 60) — хорошая практика для challenge-записей. Но если до добавления TXT резолвер успел получить NXDOMAIN на _acme-challenge, он мог закэшировать отрицательный ответ на время, зависящее от SOA (negative TTL). В итоге вы уже добавили TXT на authoritative, а часть резолверов ещё «уверена», что записи нет.

Поэтому при отладке проверяйте authoritative напрямую (через dig @nsX), а в автоматизации закладывайте адекватный delay ожидания propagation.

Типовые ошибки update-policy и как их быстро распознать

REFUSED при nsupdate/lego

Чаще всего это одна из причин:

  • не совпали имя/секрет/алгоритм TSIG;
  • в update-policy нет правила, которое подходит именно под обновляемое имя и тип;
  • update попадает в другой view (split-horizon), где нет нужного update-policy.

Смотрите логи named и для начала упрощайте тест: выполняйте update локально и явно задавайте server в nsupdate.

TXT появился на master, но не дошёл до secondary

Это почти всегда проблема transfer/notify. Проверьте:

  • что secondary действительно настроен как slave для зоны и знает master;
  • что master разрешает AXFR/IXFR этому secondary (ACL не режет transfer);
  • что notify не отключён (по умолчанию включён) и secondary доступен по сети.

Если у вас несколько площадок, закладывайте propagation по худшему NS (часто это самый «дальний» secondary).

lego добавляет TXT, но ACME-проверка падает

Типичный сценарий: слишком короткое ожидание propagation и проверка только одного NS при диагностике. Увеличьте delay/timeout и проверяйте TXT на всех NS из делегирования. Ещё нюанс: некоторые клиенты создают несколько TXT на одном имени. Это нормально, BIND поддерживает несколько TXT, но в своих скриптах не делайте «грубую» чистку всех TXT в _acme-challenge, если у вас возможны параллельные запросы.

Пример диагностики: nsupdate добавляет TXT, dig проверяет TXT и SOA serial на разных NS

Эксплуатация: параллельные renew, чистка TXT и безопасность

В продакшене чаще ломается не первая выдача, а автоматизация и параллельность. Что обычно помогает:

  • Один пайплайн обновления сертификатов на зону/имя за раз (избегайте гонок на создании/удалении TXT).
  • TSIG-ключу выдавайте минимально необходимые права: только _acme-challenge и только txt.
  • Храните секреты отдельно от репозиториев и ротуйте ключи при любых подозрениях.
  • Ориентируйтесь на худший по скорости secondary при выборе delay/timeout.

Если у вас BIND и ACME-автоматизация крутятся на отдельной машине, часто удобнее вынести это на отдельный сервер. Под такую задачу обычно берут VDS, чтобы держать DNS, мониторинг и обновление сертификатов в одном месте и контролировать сетевой доступ к RFC2136.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Чек-лист быстрой диагностики DNS-01 (RFC2136 + BIND)

  1. TXT появился на master при запросе напрямую?
  2. TXT появился на каждом NS из делегирования?
  3. SOA serial на secondary обновился?
  4. Нет ли влияния negative caching (особенно если раньше было NXDOMAIN)?
  5. update-policy ограничивает только нужное имя и тип?
  6. Нет ли views/split-horizon, из-за которых update и публичные ответы идут в разные view?

Итог

ACME DNS-01 для wildcard через RFC2136 и BIND отлично работает, если соблюдены два условия: строго ограниченный доступ через TSIG и update-policy (только _acme-challenge и только txt), а также понимание propagation как цепочки master → secondary → authoritative NS, куда реально придёт CA.

Отладьте базу через nsupdate и проверки dig @nsX по всем NS, и тогда интеграция lego обычно становится финальным техническим шагом, а не лотереей на таймингах.

Поделиться статьей

Вам будет интересно

Debian/Ubuntu: duplicate address detected, DAD failed IPv6 — причины и исправление OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: duplicate address detected, DAD failed IPv6 — причины и исправление

Сообщения duplicate address detected и DAD failed в Debian/Ubuntu означают, что IPv6-адрес не прошёл проверку уникальности в локал ...
Debian/Ubuntu: как исправить swapoff: Device or resource busy при отключении swap OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить swapoff: Device or resource busy при отключении swap

Ошибка swapoff: Device or resource busy в Debian и Ubuntu обычно связана не с «битым» swap, а с нехваткой RAM, zram, автоподключен ...
Debian/Ubuntu: как исправить cloud-init status: error после first boot на VDS OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить cloud-init status: error после first boot на VDS

Если на Debian или Ubuntu после первого запуска или клонирования VDS вы видите cloud-init status: error, причина обычно в datasour ...