Привет, Хабр! Я разработчик сервиса Leopult.ru— платформы для создания сайтов муниципальных учреждений. Уже 11 лет мы помогаем десяткам тысяч клиентов в России запускать и поддерживать их веб-ресурсы. Сегодня я расскажу о своем расследовании загадочной ошибки при выпуске wildcard-сертификатов через Let's Encrypt.
Если вы сталкивались с acme: error: 403 :: urn:ietf:params:acme:error:unauthorized :: No TXT record found
, то эта история для вас. Погрузимся в мир DNS, API и, возможно, теней РКН, чтобы понять, почему сертификаты перестали выдаваться, и как я это починил.
Спойлер: виноваты не только DNS-серверы!
Проlog: Когда сертификаты перестали работать
На нашей платформе Leopult.ru мы активно используем wildcard-сертификаты Let's Encrypt для обеспечения HTTPS на сайтах клиентов. Для автоматизации их выпуска я использую [lego](https://github.com/go-acme/lego) в Docker с DNS-01 challenge, а DNS хостится на Selectel. Всё работало как часы: lego
через API добавлял TXT-запись в _acme-challenge.<домен>
, Let's Encrypt её видел, и сертификат выпускался. Но пару дней назад — бум! — ошибка:
2025/07/05 20:34:44 Could not obtain certificates: error: one or more domains had a problem: [*.example.ru] acme: error: 403 :: urn:ietf:params:acme:error:unauthorized :: During secondary validation: No TXT record found at acme-challenge.example.ru
Лог lego показал, что TXT-запись создается, но Let's Encrypt её не видит при вторичной проверке. Я проверил панель Selectel: запись на месте. Это было похоже на детектив: где-то в цепочке DNS или API что-то сломалось. Пора начинать расследование!
Гипотеза 1: Проблема с API Selectel
Первым делом я заподозрил API Selectel. Для Leopult.ru мы используем провайдер selectelv2 в lego, чтобы автоматически добавлять TXT-записи. Проверив панель управления Selectel, я убедился: запись создается, вот пример: ` acme-challenge.example.ru. TXT "FiIz_y_uuHTqprekGh3a14vjW..." ` API работает, токен валидный, запись появляется. Но если Let's Encrypt её не видит, может, проблема в синхронизации серверов Selectel? Я решил проверить это с помощью dig: `bash dig TXT acme-challenge.example.ru @ns1.selectel.ru ` Ответ вернулся мгновенно, запись на месте. То же самое с ns2.selectel.ru. Авторитетные серверы Selectel знают о записи, но публичные DNS (1.1.1.1, 8.8.8.8) её не видели. Пора копать в сторону DNS-пропагации.
Гипотеза 2: Пропагация DNS — где ты?
Логи lego подсказали:
2025/07/05 20:34:31 [INFO] [*.
example.ru
] acme: Checking DNS record propagation. [nameservers=1.1.1.1:53,8.8.8.8:53] 2025/07/05 20:34:36 [INFO] Wait for propagation [timeout: 2m0s, interval: 5s]
lego ждёт всего 2 минуты на распространение записи. Но что, если Selectel медленнее синхронизирует DNS? TTL записи в панели был 60 секунд — вполне разумно. Однако публичные DNS-серверы упорно не видели запись. Я написал простой скрипт для мониторинга:
while true; do dig TXT _acme-challenge.example.ru @1.1.1.1 +short; sleep 1; done
Ни сразу ни через несколько минут запись непоявилась, Это намекало на проблемы с глобальной синхронизацией DNS. Я увеличил таймаут в lego до 10 минут: `bash --dns-timeout 600 ` Ошибка 403 осталась. Пора было углубиться в механику Let's Encrypt.
Гипотеза 3: Вторичная проверка Let's Encrypt
Let's Encrypt использует вторичную проверку: TXT-запись проверяется с разных сетевых узлов, чтобы исключить манипуляции DNS. Если хотя бы один узел не видит запись, выдаётся ошибка 403. Я предположил, что стандартные DNS-серверы (1.1.1.1, 8.8.8.8) могут быть не лучшим выбором. Вдруг они фильтруются или медленно обновляются? Я решил попробовать авторитетные серверы Selectel в качестве резолверов для lego:
bash --dns.resolvers 188.68.203.1:53,77.223.114.2:53
Где 188.68.203.1 и 77.223.114.2 — IP-адреса a.ns.selectel.ru и b.ns.selectel.ru. И — о чудо! — сертификат выпущен! Это был прорыв. Но оставались вопросы: почему публичные DNS не работают, и можно ли доверять IP-адресам Selectel?
Гипотеза 4: Тень РКН?
С учётом новостей о блокировках РКН я задумался: может, проблема связана с ограничениями на публичные DNS, такие как Cloudflare (1.1.1.1)? В России иногда возникают проблемы с доступом к сервисам, и это могло повлиять на вторичную проверку Let's Encrypt. Я протестировал другие DNS-серверы:
dig TXT _acme-challenge.example.ru @9.9.9.9
Quad9 (9.9.9.9) тоже не видел запись стабильно. Это укрепило подозрения, что проблема может быть связана с сетевыми ограничениями или неравномерной синхронизацией DNS на стороне Selectel.
Развязка: Письмо в поддержку и временное решение
Чтобы докопаться до истины, я написал в поддержку Selectel, и пока ждал ответа сделал временное решение а именно прописал в lego dns-резолверы селектел:
docker run --rm \
-e SELECTELV2_TOKEN="мой_токен" \
goacme/lego \
--email "my@email.com" \
--domains "*.example.ru" \
--domains "example.ru" \
--dns selectelv2 \
--dns-timeout 600 \
--dns.resolvers 188.68.203.1:53,77.223.114.2:53 \
run
Итоги расследования
Пока поддержка Selectel молчит, я склоняюсь к тому, что проблема связана с неравномерной синхронизацией DNS или ограничениями на публичные DNS (возможно, из-за РКН). Использование авторитетных серверов Selectel как резолверов решило проблему, но это временный костыль. На Leopult.ru мы обслуживаем десятки тысяч клиентов, и стабильность HTTPS для нас критически важна, так что я надеюсь на разъяснения от Selectel.
Если вы сталкивались с подобными граблями, делитесь в комментариях своими находками! Может, у @HabrCommunity есть идеи, как обойти такие проблемы без смены DNS-провайдера? А пока мой сервер снова раздаёт HTTPS, и сайты клиентов Leopult.ru работают без сбоев. Но это только первая глава — жду ответа от поддержки, чтобы закрыть дело. Stay tuned, Хабр!
Комментарии (3)
WinLin2
06.07.2025 00:46При использовании yandex-dns выдавались ошибки от 40 минут ожидания. Сейчас использую иностранный dns, но не google, и уже через 2 минуты стабильно создаются записи.
litos
06.07.2025 00:46LE проверяя запись ведь идёт напрямую на NS сервера на которые деленирован домен? Видимо не может подключиться к ним или как-то ещё ограничен?
riv9231
РКН непричём? Удивительно!