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

Let's Encrypt за CDN и прокси: HTTP‑01 проблемы и переход на DNS‑01

HTTP‑01 проверка Let's Encrypt часто падает, когда сайт спрятан за CDN или обратным прокси: редиректы, кеш, IPv6, WAF и закрытый 80 порт. Разбираем, как работает ACME, почему HTTP‑01 ненадежен в такой архитектуре и как перейти на DNS‑01: TXT‑записи, плагины, автоматизация ротации и типовые ошибки.
Let's Encrypt за CDN и прокси: HTTP‑01 проблемы и переход на DNS‑01

Если ваш сайт под CDN, за ним обратный прокси или балансировщик, «обычный» выпуск сертификата через Let's Encrypt с проверкой http-01 рано или поздно начинает сбоить. Типичные жалобы: «сертификат не продлился ночью», «вчера работало, сегодня 403 на валидации», «IPv6 ушел на CDN и все упало». Решение, проверенное практикой: перейти на dns-01. Ниже разберем, почему http-01 нестабилен за CDN/reverse proxy, как правильно внедрить dns-01, какие подводные камни у TXT-записей и как автоматизировать ротацию SSL без даунтайма.

Как ACME-проверки устроены и что мешает за прокси

Сервисы ACME (в первую очередь Let's Encrypt) предлагают несколько способов доказать владение доменом:

  • http-01 — проверяющий ходит по HTTP на http://example.com/.well-known/acme-challenge/<token> и ожидает конкретный ответ. Разрешены 301/302 на HTTPS, но результат должен совпасть.
  • tls-alpn-01 — проверяющий стучится на 443 и ожидает специальный ALPN и сертификат-соответствие токену на самом хосте. За TLS-терминацией это почти всегда ломается: виден CDN, а не ваш origin.
  • dns-01 — проверяющий читает TXT у _acme-challenge.example.com и сверяет значение. Состояние 80/443 здесь не важно — критичен только DNS.

Когда домен спрятан за CDN или обратным прокси, первые два способа «натыкаются» на чужую терминацию, агрессивный кеш, переписывание локаций и фильтрацию трафика. Именно поэтому dns-01 практически универсален: контроль принадлежности домена осуществляется в DNS.

Почему http-01 нестабилен за CDN и reverse proxy

В бою мы видим повторяющийся набор проблем, из-за которых автоматическое продление рвется в самый неподходящий момент:

  • Порт 80 закрыт на периметре. Для http-01 это фатально: валидатор обязан достучаться до HTTP.
  • Принудительный редирект на HTTPS, а на 443 висит CDN c нестандартными правилами. Формально редирект допустим, но дальше прилетает не тот контент.
  • WAF/CDN режут запросы по User-Agent или rate limit. Проверка получает 403/429.
  • Кеширование и оптимизации CDN: /.well-known/acme-challenge/ могут минифицировать, сжимать, менять заголовки — хеш не сходится.
  • Несогласованность A/AAAA. Есть AAAA на CDN и A на origin; валидатор предпочел IPv6 и уперся не туда.
  • Базовая авторизация, IP-алловлист и VPN. Валидатор упирается в 401/403 или не входит в разрешенный список.
  • Неверная маршрутизация в прокси. Нет явного location для /.well-known — запрос уходит в приложение и получает 404/405.
  • Мульти-CDN и канареечные релизы. В одном регионе новая конфигурация пропускает валидацию, в другом старая — режет.

Все это может работать «месяцами», а затем внезапно сломаться после невинного изменения в конфигурации CDN, правил кеша или порядка listen-директив. В продакшене так жить нельзя.

Пример server-блока Nginx для выдачи ACME-челенджа без редиректов

Костыли для http-01 и почему их лучше избегать

Да, можно попытаться подружить проверку с инфраструктурой: открыть 80, прописать исключение для /.well-known/acme-challenge/, отключить кеш и WAF на этой папке, поднять отдельный виртуальный хост только ради челенджа. Это работает, но сопровождается большим количеством допущений и точек отказа. Чем сложнее периметр, тем выше шанс, что очередной редирект или IPv6-переключение снова сломают продление.

Если все же идете этим путем, добавьте явный location в прокси, который минует фильтры и кеши, отдает файл из webroot и не делает редиректов. Пример для Nginx (минимальный скелет):

server {
    listen 80;
    server_name example.com www.example.com;

    location ^~ /.well-known/acme-challenge/ {
        default_type text/plain;
        root /var/www/letsencrypt;
        add_header Cache-Control no-store;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

Однако даже при таком упрощенном сервере вы зависите от внешнего CDN, который может перехватывать 80 или менять поведение по регионам. Для устойчивого продакшена лучше перейти на dns-01.

Почему dns-01 выигрывает

dns-01 подтверждает владение доменом через TXT-запись в зоне: ACME-валидатор читает _acme-challenge.example.com и сверяет значение с ожиданием. Преимущества:

  • Независимость от HTTP и TLS-терминации. Хоть полностью выключите сайт — продление пройдет.
  • Работает за любыми CDN, балансировщиками и прокси.
  • Поддерживает wildcard-сертификаты (*.example.com), которые http-01 не выпускает. См. подробное руководство Wildcard SSL через DNS‑01: полная автоматизация.
  • Удобная автоматизация через API DNS-провайдера или RFC 2136 для собственного DNS.

Главная тонкость — корректно и безопасно автоматизировать создание и удаление TXT-записей и учесть задержки распространения DNS.

Переход на dns-01: стратегия миграции

Рекомендуем не выключать текущую схему до первого успешного выпуска через dns-01. Типовой план:

  1. Подготовьте ACME-клиент (или плагин) для dns-01 в staging-окружении, чтобы не поймать лимиты.
  2. Настройте доступ к API вашего DNS с минимальными правами: только редактирование TXT в нужной зоне.
  3. Сделайте тестовый выпуск для одного поддомена, проверьте корректность TTL и время распространения.
  4. Переведите основной домен на dns-01, проверьте автопродление и перезагрузку веб-сервера без даунтайма.
  5. Опционально: добавьте wildcard и объедините SAN-наборы (апекс и www) в один заказ сертификата. О лимитах и SAN см. ограничения Let's Encrypt и автоматизация.

Certbot: плагин для DNS

Certbot поддерживает множество DNS-плагинов. Принцип одинаков: вы кладете учетные данные API в конфиг с правами 0600 и вызываете certbot с провайдером, указывая домены. Дальше certbot сам создаст TXT, подождет распространения, подтвердит и удалит запись. Базовая схема команд:

# Установка плагина под вашего DNS-провайдера (пример: certbot-dns-xyz)
# Первый выпуск в staging (без рисков по лимитам)
certbot certonly --dns-xyz --dns-xyz-credentials /etc/letsencrypt/dns-xyz.ini --server https://acme-staging-v02.api.letsencrypt.org/directory -d example.com -d www.example.com
# Продакшн выпуск, при необходимости с wildcard
certbot certonly --dns-xyz --dns-xyz-credentials /etc/letsencrypt/dns-xyz.ini -d example.com -d www.example.com -d *.example.com
# Хук на перезагрузку веб-сервера при продлении
certbot renew --deploy-hook "nginx -t && nginx -s reload"

У разных провайдеров есть опции ожидания распространения (sleep). Для нестабильных зон разумно закладывать 60–120 секунд и проверять авторитативные NS.

acme.sh: легкий и гибкий клиент

acme.sh удобен большим количеством встроенных DNS-интеграций и простыми деплой-хуками. Общий подход:

# Установка в домашний каталог
curl -s https://get.acme.sh | sh
# Переключение на Let's Encrypt (если нужно)
~/.acme.sh/acme.sh --set-default-ca --server letsencrypt
# Экспорт переменных окружения с токеном API провайдера
export XYZ_OAUTH_TOKEN="..."
# Выпуск через DNS, SAN + wildcard
~/.acme.sh/acme.sh --issue --dns dns_xyz -d example.com -d www.example.com -d *.example.com
# Установка сертификатов и перезагрузка Nginx
~/.acme.sh/acme.sh --install-cert -d example.com --key-file /etc/ssl/private/example.com.key --fullchain-file /etc/ssl/certs/example.com.fullchain.pem --reloadcmd "nginx -t && nginx -s reload"

Для зон с медленным DNS предусмотрена опция ожидания --dnssleep, а для сложных сценариев — делегирование CNAME: указываете _acme-challenge.example.com на специальный поддомен, которым управляет отдельный технический аккаунт.

Другие клиенты: lego, dehydrated

lego и dehydrated также поддерживают dns-01 и многочисленные DNS-провайдеры. Принципы одинаковы: храните токены отдельно, используйте staging при отладке, закладывайте паузу на распространение и добавляйте хук на перезагрузку веб-сервиса.

DNS-провайдер и права доступа

Чтобы автоматизация была безопасной, принцип минимальных прав обязателен: токен должен позволять менять только TXT в одной зоне (или даже только под _acme-challenge). Храните учетные данные в файле с правами 0600, следите за журналами действий. Для собственного DNS (Bind/PowerDNS) подходит RFC 2136: выпускаете TSIG-ключ, разрешаете обновления только с нужного IP и имени ключа.

Если TTL у зоны большой (например, 3600), задайте меньший TTL для _acme-challenge или делегируйте поддомен на быстрый DNS. Популярная практика — завести _acme-challenge.example.com как CNAME на _acme-challenge.acme.example.net, которым управляет автоматизация.

FastFox VDS
Регистрация доменов от 99 руб.
Каждый проект заслуживает идеального доменного имени, выберите один из сотни, чтобы начать работу!

Тонкости dns-01 в продакшене

  • Несколько значений TXT одновременно. Для SAN-заказов валидатор может требовать несколько значений под одним именем. Не удаляйте предыдущие до завершения всех проверок.
  • Wildcard и апекс вместе. _acme-challenge.example.com используется и для example.com, и для *.example.com — значения должны сосуществовать.
  • Кавычки и длина. Некоторые панели отображают TXT в кавычках или разбивают на части — это нормально, лишь бы итоговая строка совпала. Не вставляйте лишние пробелы.
  • Негативный кеш. NXDOMAIN по TXT может закешироваться у рекурсивного резолвера. Проверяйте авторитативные NS и закладывайте паузу.
  • Окно проверки ACME. После создания TXT у вас ограниченное время на подтверждение. Клиенты обычно сами дергают challenge, но не растягивайте процесс.
  • Удаление TXT после успеха. Это безопасно и полезно, чтобы не скапливать старые значения.
  • Staging перед продакшеном. Сначала обкатайте dns-01 на тестовой директории ACME, чтобы не упереться в лимиты.

Автоматизация ротации сертификатов

Как только выпуск освоен, настройте безостановочную ротацию:

  • Планировщик. Для certbot — systemd timer или cron дважды в день; для acme.sh — встроенный cron при установке.
  • Проверка конфигурации перед перегрузкой. Для Nginx делайте nginx -t и только затем nginx -s reload. Для Apache — apachectl configtest и graceful.
  • Многосерверные инсталляции. Выпускать можно на одном узле и распространять ключи и цепочки на остальные через безопасный канал (rsync/scp с ограниченными ключами, агенты конфигурации). Следите за правами: приватный ключ не должен быть мирово читаемым.
  • Мониторинг срока действия. Алерты за 30/14/7 дней до истечения позволят отловить неожиданные сбои DNS-автоматизации.

Процесс DNS‑01: создание TXT‑записи и ожидание распространения по DNS

Безопасность: токены и ключи

Храните токены DNS-провайдера как секреты: отдельный файл с правами 0600, владелец — пользователь, под которым работает ACME-клиент. Разделите окружения: в staging используйте отдельные токены. Ограничьте исходящие подключения хоста-выпускателя, чтобы он мог обращаться только к API провайдера и ACME-директории. Логи клиентов могут содержать отладочную информацию — не пишите в них токены.

Приватные ключи сертификатов — самый чувствительный артефакт. Раздавайте их только на те серверы, где они действительно нужны, и не копируйте в CI-агенты без крайней необходимости. Если у вас выделенная TLS-терминация, ограничьте распространение ключей только на этот периметр. Если не хотите возиться с ACME или нужен расширенный выпуск, рассмотрите коммерческие SSL-сертификаты.

Чек-лист миграции с http-01 на dns-01

  • Выберите ACME-клиент и DNS-интеграцию, подготовьте staging.
  • Создайте токен с минимальными правами, положите его в файл 0600.
  • Сделайте тестовый выпуск одного домена, проверьте время распространения TXT.
  • Настройте хук на перезагрузку веб-сервера с проверкой конфигурации.
  • Переведите боевые сертификаты, включите мониторинг срока действия.
  • Опционально: настройте CNAME-делегирование для _acme-challenge и отдельный быстрый DNS.

FAQ: частые вопросы

Можно ли остаться на tls-alpn-01 за CDN? В редких случаях — да, если вы контролируете конечную TLS-терминацию, она принимает ALPN-валидатор и пропускает нужный SNI на ваш хост. С публичными CDN почти всегда нет.

Что с IPv6? Для http-01 малейшая асимметрия между A и AAAA приводит к флаку. dns-01 полностью независим от IP-стека.

Нужно ли держать 80 открытым при dns-01? Нет. Проверки идут через DNS, порт 80 можно закрыть.

Как быть с большим TTL? Используйте отдельный поддомен под _acme-challenge и делегируйте его на DNS с коротким TTL (например, 60). Или увеличьте задержку ожидания в клиенте.

Wildcard и SAN вместе? Да, объединяйте в один заказ: example.com и *.example.com. Следите за тем, чтобы клиент создавал все необходимые TXT одновременно.

Итоги

За CDN и обратными прокси проверка http-01 — постоянный источник сюрпризов: от редиректов и кеша до IPv6 и WAF. Переход на dns-01 снимает зависимость от периметра, позволяет выпускать wildcard и делает продление предсказуемым. Важно грамотно автоматизировать работу с TXT-записями, обкатать процесс в staging, учесть задержки распространения и корректно перезагружать сервисы. После этого ротация сертификатов становится скучной рутиной — как и должно быть в продакшене.

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

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

Debian/Ubuntu: mount: wrong fs type, bad option, bad superblock — как быстро найти и исправить причину OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: mount: wrong fs type, bad option, bad superblock — как быстро найти и исправить причину

Ошибка mount: wrong fs type, bad option, bad superblock в Debian/Ubuntu может означать и простую опечатку в имени раздела, и пробл ...
Debian/Ubuntu: XFS metadata corruption и emergency read-only — пошаговое восстановление OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: XFS metadata corruption и emergency read-only — пошаговое восстановление

Если XFS-раздел внезапно стал доступен только для чтения, а сервер ушёл в emergency mode, главное — не спешить. Разберём безопасны ...
Debian/Ubuntu: как исправить Failed to fetch при apt update OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить Failed to fetch при apt update

Ошибка Failed to fetch при apt update в Debian и Ubuntu обычно связана не с самим APT, а с DNS, сетью, зеркалом, прокси, временем ...