Перед аудитом мы ротировали сертификат на стенде, а старый отправили в отзыв - обычная гигиена. Мне захотелось убедиться, что отзыв действительно сработал: поднял на отдельном порту сервис со старым сертификатом и открыл его в браузере.
Браузер открыл страницу. Замок на месте, предупреждений нет.
Первая мысль была, что отзыв не прошёл: запрос ушёл не туда, серийный номер не тот, удостоверяющий центр ещё не обновил список. Проверил сам - скачал список отзыва по адресу из сертификата и нашёл в нём его серийный номер с датой отзыва. Отозван. Он этого не учитывает, потому что не проверяет.
Проверять отзыв никто не обязан
Сертификат - это утверждение удостоверяющего центра, что такой-то ключ принадлежит такому-то домену. Утверждение сделано один раз, на срок действия, и лежит оно на сервере. Отзыв - это отдельное утверждение центра, что предыдущее больше не в силе, и лежит оно у центра.
Отсюда вся конструкция: чтобы узнать про отзыв, клиенту надо сходить к третьей стороне в момент подключения. И вот здесь всё и ломается - по причинам не криптографическим, а вполне бытовым.
Задержка. Лишний сетевой запрос перед каждым новым TLS-соединением. На плохой связи он заметен, и заметен он на каждой странице, а не только на той, где что-то не так.
Приватность. Запрос к удостоверяющему центру сообщает ему, какой сайт вы открываете и когда. Тот, кто выдал сертификат, получает журнал посещений всех сайтов с его сертификатами.
Что делать, если ответа нет. Это главный вопрос. Если считать «нет ответа» ошибкой и рвать соединение, то любой сбой у центра кладёт половину интернета. Если не рвать - проверка ничего не даёт: тому, кто и так контролирует канал, достаточно уронить запрос к центру. Победил второй вариант, он называется soft-fail. Ровно поэтому проверка отзыва во всех массовых браузерах - не проверка, а формальность.
Здесь стоит развести два разных подхода, потому что их часто смешивают.
Chrome и производные онлайн-проверок для обычных сертификатов не делают вообще. Вместо этого список отозванных сертификатов (CRLSet) доставляется в браузер отдельным компонентом; собирает его Google автоматически из списков отзыва удостоверяющих центров и урезает по своим правилам - в него попадает лишь часть отзывов, а не все.
Firefox с версии 137 по умолчанию использует CRLite - собственный компактный агрегат, куда помещаются отзывы целиком. Для сертификата, покрытого этим агрегатом, решение принимается локально и мгновенно, и это уже не soft-fail: отзыв либо известен, либо нет, и в сеть браузер не ходит. OCSP с soft-fail сохраняется для того, что агрегатом не покрыто.
Общее у обоих подходов одно: браузер полагается не на ответ центра в момент подключения, а на то, что кто-то заранее собрал список за него.
Проверить статус можно, и это полезно
Ручная проверка никуда не делась, просто её делает не браузер, а вы.
$ openssl s_client -connect letsencrypt.org:443 -servername letsencrypt.org </dev/null 2>/dev/null \ | openssl x509 -noout -issuer -ocsp_uri -ext crlDistributionPoints
Показательно, что у сертификатов Let’s Encrypt адреса OCSP в ответе больше нет - остался только список отзыва:
issuer=C=US, O=Let's Encrypt, CN=YE2 X509v3 CRL Distribution Points: Full Name: URI:http://ye2.c.lencr.org/58.crl
Let’s Encrypt выключил OCSP, и причины назвал прямо: сервис создавал огромную нагрузку, стоил денег, раскрывал центру посещения пользователей и при этом ни на что не влиял из-за soft-fail. Остались списки отзыва - и они, в отличие от OCSP, режутся на части: конкретный сертификат ссылается на конкретный кусок.
$ curl -s -o le.crl -w 'size=%{size_download}\n' http://ye2.c.lencr.org/58.crl size=57997 $ openssl crl -inform DER -in le.crl -noout -text | grep -c 'Serial Number' 1485
58 килобайт, 1485 отозванных сертификатов в одном куске - это на момент, когда я смотрел; файл живой, у вас числа будут другими. Скачивается быстро, но качать список перед каждым соединением всё равно никто не станет, и мы возвращаемся туда же, откуда пришли.
Ставить ответ центра рядом с сертификатом
Способ обойти и задержку, и приватность придумали давно: сервер сам ходит к удостоверяющему центру, получает подписанный ответ «сертификат в силе» и прикладывает его к рукопожатию. Клиент при этом никуда не обращается, ответ подписан центром и подделать его нельзя. Называется это OCSP stapling.
Дыр тут две. Первая - если ответа в рукопожатии нет, клиент просто идёт дальше; тому, кто владеет украденным ключом, достаточно ответ не прикладывать. Вторая тоньше: ответ центра подписан на несколько дней вперёд и не привязан к конкретному соединению. Значит, «good», полученный до отзыва, остаётся валидным ответом ещё некоторое время после него, и его можно прикладывать дальше.
Латали это расширением Must-Staple: в сам сертификат ставится флаг «у меня ответ обязан быть, нет ответа - рви соединение». Работало. Пользовались единицы, потому что цена ошибки высокая: настроил неаккуратно, сервер перестал получать ответы от центра - и сайт перестал открываться у всех, у кого этот флаг поддерживается. А теперь, когда крупнейший центр OCSP выключил, для его сертификатов флаг не имеет смысла в принципе.
Я бы Must-Staple сегодня не советовал. Не потому, что идея плохая - идея правильная, - а потому, что механизм, на который она опирается, отрасль сворачивает.
Настоящее решение оказалось скучным
Раз отозвать сертификат надёжно нельзя, отрасль пошла другим путём: сделать срок жизни сертификата таким коротким, чтобы отзыв не требовался. Просроченный сертификат отвергают практически все клиенты, и эта проверка не требует ни сети, ни третьей стороны - дата лежит внутри сертификата. Упирается она только в правильность часов на клиенте, и именно поэтому встроенные устройства без часов реального времени остаются отдельной больной темой.
Календарь утверждён бюллетенем SC-081v3 в апреле 2025 года: до 14 марта 2026 года максимум 398 дней, с 15 марта 2026 года - 200 дней, с 15 марта 2027 года - 100 дней, с 15 марта 2029 года - 47 дней.
Это видно уже сейчас, если посмотреть на даты в сертификатах:
letsencrypt.org: notBefore=Jul 6 15:24:34 2026 GMT notAfter=Oct 4 15:24:33 2026 GMT github.com: notBefore=Sep 1 00:00:00 2026 GMT notAfter=Nov 29 23:59:59 2026 GMT
Девяносто дней у обоих. Сертификаты, выданные до марта 2026 года, ещё живут по году с лишним - но они последние.
Из этого следует практический вывод, и он не про безопасность, а про эксплуатацию. Ручное обновление раз в год - одна операция в год, её можно делать по календарному напоминанию. При сроке в 47 дней истечений в году получается около восьми, а обновляют не в последний день, а с запасом - то есть подходить к каждому сертификату придётся раз в две-три недели. Если сертификатов полсотни, ручной режим кончился. Автоматизация выпуска перестала быть удобством и стала условием работы сайта.
Где всё это по-прежнему проверяется всерьёз
Картина «отзыв не работает» верна для публичного веба и браузеров. Там, где стороны знают друг друга, всё иначе.
Внутренний удостоверяющий центр под клиентские сертификаты сотрудников: список отзыва небольшой, доступен всегда, и режим hard-fail включается спокойно - при недоступности центра сервис и так не работает. То же с подписью кода, где проверка идёт с отметкой времени, и с сертификатами устройств в закрытых сетях.
Разница не в криптографии, а в том, кто платит за отказ. В публичном вебе за строгую проверку платит случайный пользователь, который ни при чём. Во внутренней системе - её же владелец, и он может принять это решение осознанно.
Что посмотреть у себя
Есть ли у вас сертификат, который вы считаете отозванным, и продолжает ли он приниматься. Проверять надо тем клиентом, который у вас реально обращается по этому адресу, а не браузером: библиотеки в приложениях по умолчанию отзыв чаще всего не проверяют вообще.
Посмотреть срок действия ваших сертификатов и посчитать, сколько обновлений в год получится при сроке в 100 дней. Если ответ «мы не успеем» - это задача на ближайший год, а не на 2029-й.
Проверить, что происходит при недоступности удостоверяющего центра во внутреннем контуре, если вы там включили строгую проверку. Тестируется это блокировкой адреса центра на файрволе, а не рассуждением.
И отдельно: понять, что вы вообще сделаете, если ключ от сертификата утечёт. Ответ «отзовём» неполный. Правильный ответ - «выпустим новый, выкатим, и до конца срока старого будем считать, что он живой», а из этого сразу следует, какой срок жизни для вас приемлем.

