На работе досталась задача по решению проблем и мониторингу сертификатов на ISP Manager.
Внесем немного ясности. Когда речь идет о десятках сайтов, имхо ISP избыточен, но когда их 1000 и над проектом работают люди с разной квалификацией, то веб-интерфейс будет крайне удобен.
Наша компания предоставляет готовые шаблоны сайтов интегрированные с другим нашим продуктом. С нашей стороны полный пакет обслуживания: доступность, стабильность и безопасность. Все технические вопросы решаем мы, никаких cloudflare
, мы и без них хорошо справляемся (другими сервисами). Клиентам остается только припарковать к нам домен и лить трафик, дальше работаем мы.
На дворе 2023 год, https
уже мейнстрим, поэтому без сертификатов никак. Юзаем let's encrypt (еще бы, ведь обслуживаем тысячи доменов).
Оказалось, что из-за большого количества доменов и клиентов образовался большой уровень энтропии.
Кто-то скрыл свой домен за обратным прокси типа cloudflare или в
dns
полный бардак. Кто-то уже давно от нас ушел, а где-то просто домены уже свободны по разным причинам. Но сайты на ISP до сих пор активны и есть просроченные сертификаты.
Мне удалось выяснить несколько видов проблем:
A записей
или домен свободен - ответ acme сервера
403
acme сервера
429
nginx
:nginx SSL: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch
Рассмотрим каждую проблему.
Здесь все просто: нам нужно понять какие домены к нам припаркованы, а какие нет и разобраться с последними. Точнее передать менеджерам для дальнейших разборок.
Сначал для этого дела на коленке был сделан php
скрипт, но так как это однопоток и приходится долго ждать - было решено переписать на golang
. Вот репозиторий.
Здесь мы наблюдаем какой-то фантомный баг, который возникает случайно и очень редко, каких-либо закономерностей выявить не удалось. Вот обсуждение на форуме let's encrypt.
Причин этой ошибки 2 (интересная статья):
Однако, при перезапуске процесса получения сертификата все проходит успешно.
Ниже будем настраивать мониторинг, наблюдать за ситуацией и решать проблему руками, пока не выявим закономерности или причины.
В пятницу ТП ISP решили нам помочь и перевыпустить все сертификаты ... а у нас там тысячи доменов среди которых чуть меньше половины невалидны.
В понедельник начали сыпаться жалобы от клиентов: мы уперлись в лимиты и больше не могли выпускать новые сертификаты, а новые сайты продолжали регистрироваться на нашем ISP.
Стоит отдельно поговорить про лимиты, так как не понятно о чем вообще идет речь?
Читая форумы и разбирая acme спецификацию я пришел к выводу что процесс выпуска сертификата для домена включает в себя авторизацию домена на acme сервере
. Эта авторизация прекращается после выпуска сертификата или посредством отзыва авторизации через acme клиент
.
Что происходило в нашем случае:
acme сервере
Как правило на одном web-сервере
, который взаимодействует с let's encrypt
посредством того же Certbot
, используется один аккаунт на acme сервере
, а он используется в любом случае.
Еще раз читаем доку по ограничениям от let's encrypt
и видим:
Для одного аккаунта допускается не более 300 запросов на авторизацию, ожидающих ответа.
У нас накопилось более 300 процедур выпуска сертификата и мы начали получать ответ от acme сервера
:
Из этого обсуждения удалось выяснить что авторизация для домена истекает через 7 дней при бездействии (pendingAuthorizationLifetimeDays
).
Выходит, нам нужно ждать пока авторизации начнут отменятся самим acme сервером
по истечении 7-ми дней после их создания, но когда это начнется не понятно. Либо самим отменять авторизацию.
Оказалось что в такой ситуации мы не одиноки, есть проекты на тему отмены авторизации доменов. Например acmecancel, LE_FIND_PENDING_AUTHZ и letsdebug-toolkit, а clear-authz вообще веб (ссылка на реп).
Но большая часть этих проектов работает по старому протоколу v01
, а у нас уже v02.
Да и не имеет это смысла, потому что в логах у нас нет enpoint
authz
с нашими нужными доменами. Возможно потому что наш certbot
версии 0.33
.
Есть еще полезные статьи от ISP как они вели разработку плагина сертификатов вот и вот.
Собрав всю мощь знаний интернета за день изучения, у нас назрели 2 пути решения проблемы:
acme аккаунт
тем самым сбрасывая все авторизации доменов и создаем новыйПеречитал начало 7.4 и раздел 7.4.1 спецификации acme
, план по самостоятельному закрытию авторизаций может не прокатить, надо тестить. А последствия второго неизвестны, хотя на формуах по ссылкам выше есть посты с подобными рекомендациями.
Вероятность выхода из лимитов увеличивается с каждым днем и на третий день мы вышли из лимитов.
Переписка с ТП ISP по этому инциденту не дала результатов, баг не признают, в планах этого нет. Но зато они подсказали что можно отправить фичреквест. Я опубликовал фичреквест и он был принят в бэклог.
После всех приключений у меня сформировалось представление что нужно мониторить и где нужны звонки, чтобы во время предупреждать инциденты.
Первым делом я обратился к поиску встроенных в ISP решений по мониторингу. Их нет, ТП подтверждает. Значит нужно выкручиваться самим.
Я и есть тот самый профильный специалист, но мне хотелось использовать готовые решения.
Оказывается у самого ISP есть БД на sqlite расположенная по пути
/usr/local/mgr5/etc/ispmgr.db
.
Немного пошарив нашлись интересные таблицы:
letsencrypt_ssl
- информация о сертификатахwebdomain
- здесь все о доменахletsencrypt_log
- а это очевидно логНа основании решаемых проблем и имеющихся для мониторинга данных составляем следующие метрики для мониторинга.
Как правило у нас единицы или десятки доменов одновременно получают сертификат, но если это массовое явление то это предвестник проблемы. Поэтому настраиваем звонок на значение меньше лимитов (>=100
) чтобы вовремя вмешаться:
SELECT COUNT(*)
FROM letsencrypt_ssl
WHERE processing = 'on'
Как мы уже знаем ISP не отменяет авторизацию домена на acme сервере
, значит нам нужно следить за количеством доменов, которые не смогли получить сертификат. Не дожидаемся значения 300 и заранее звоним (>=50
).
SELECT COUNT(*)
FROM letsencrypt_ssl
WHERE letsencrypt_ssl.failed = 'on'
Когда к нам приходит клиент у него может быть домен еще не настроен. Но даже после настройки доменной зоны, она может обновляться еще некоторое время, поэтому нам надо следить за тем какое количество доменов сейчас не может получить сертификат чтобы вовремя вмешаться в процесс.
Например, если за последние 4 часа более 20 доменов не могут получить сертификаты.
SELECT COUNT(*)
FROM (
SELECT certname, COUNT(certname) as c
FROM letsencrypt_log
WHERE status = 'failed' AND date >= DATETIME('now', '-4 hour')
GROUP BY certname
)
WHERE c > 1
Certbot
заранее обновляет сертификаты, но может произойти сбой обновления.
Такие случае возможны если не удалось вставить серт в nginx
или если клиент изменил доменную зону. Возможно есть другая проблема, в любом случае нам нужно вмешаться и выяснить чтобы проблемы не копились и уровень энтропии не увеличился.
SELECT COUNT(*)
FROM letsencrypt_ssl
WHERE processing = 'off'
AND failed == 'off'
AND ((unixepoch('now') - unixepoch(time_started)) / 60 / 60 / 24) >= (90 - 7)
У кого sqlite ниже 3.38 вместо unixepoch можно использовать strftime.
Весь http
трафик должен идти через https
. Звонков не ставим, пока смотрим графики самостоятельно, по ходу накопления данных принимаем решение.
Не настроен редирект с http
на https
:
SELECT COUNT(*)
FROM webdomain
WHERE redirect_http = 'off' AND active = 'on'
Домены без сертификатов:
SELECT *
FROM webdomain
WHERE active = 'on' AND secure == 'off'
Нулевого уровня энтропии достичь не получится, даже если он и будет на нуле то недолго, однако стремление к нулевому уровню нивелирует инциденты. Основные факторы позволяющие избежать инцидентов: