Cloudflare обслуживает более 20 процентов глобального интернет-трафика запросов и терминирует TLS для миллионов доменов, полагаясь на миллионы сертификатов в год. До сих пор эти сертификаты выдавались через чужие удостоверяющие центры. Теперь компания строит собственный удостоверяющий центрCA — организация, которая выпускает и подписывает сертификаты, подтверждая связь домена с открытым ключом и одновременно покупает уже доверенный корень. Разберём, почему выбраны оба пути, как устроена цепочка доверия, что именно требует протокол выдачи и как планируется переход к постквантовым сертификатам.
Два пути к доверию и зачем оба сразу
Браузер доверяет сертификату только тогда, когда может построить цепочку до корня, лежащего в его хранилище доверенных корней. Есть два способа туда попасть.
Первый — создать новый корневой сертификат и подать его на включение в корневые программы. Cloudflare так и сделала: заявки поданы в программы Chrome, Apple, Microsoft и Mozilla. Но совершенно новый корень не будет широко полезен годами: после принятия в корневую программу он должен распространиться по операционным системам, браузерам и устройствам, а до устройств, переставших получать обновления, он вообще не дойдёт.
Второй путь — купить уже существующий широко доверенный корень. Cloudflare подписала окончательное соглашение о приобретении такого корня у GlobalSign. Этот корень доверяется в браузерах, операционных системах и устройствах с 2012 года и достигает старых клиентов, до которых новый корень никогда не доберётся. Приобретение корня с высоким охватом хранилищ решает проблему охвата старых клиентов с первого дня.
Новый корень при этом не лишён смысла: он построен с учётом направления развития экосистемы, включая программы, начинающие ограничивать максимальный возраст доверенного корня. Итог — компания хочет иметь оба корня, чтобы сертификаты её CA давали максимально широкую совместимость с клиентами.
Почему собственный CA — это задача о надёжности
Сертификаты выдаются через несколько CA с основным и резервным путями, чтобы сервисы клиентов оставались доступными при сбоях CA и событиях отзыва. Опыт эксплуатации показал, что экосистема WebPKI иногда отказывает: Cloudflare сталкивался с ограничениями скорости, пограничными случаями валидации, задержкой отзыва, построением цепочек и задержкой распространения корней.
Число сертификатов, используемых ежегодно, будет быстро расти из-за сокращения максимального срока действия сертификатов, роста агентной активности и массового перехода на PQ-сертификаты. Поэтому, становясь собственным CA, Cloudflare обязуется строить надёжный и устойчивый центр, чья надёжность зависит не только от избегания ошибок, но и от ограничения влияния любой отдельной проблемы.
Технически это означает, что процессы проектирования и тестирования восстановления вводятся до возникновения инцидента. Конкретное следствие — автоматизация продления становится условием выдачи: сертификаты выпускаются только клиентам, поддерживающим ACME Renewal InformationARI — механизм, стандартизированный в RFC 9773, при котором CA публикует окна продления, а клиент их опрашивает. Подписчики обязаны поддерживать автоматизацию, которая опрашивает конечную точку продления, действует в соответствии с публикуемыми окнами и идентифицирует заменяемый сертификат. Без этого нельзя ни сдвинуть окна продления вперёд при необходимости отзыва, ни распределить замены по доступному времени, ни отследить выдачу замен.
Цепочка доверия: корень, промежуточные и целевой сертификат
Проверка сертификата — это построение и валидация пути от доверенной точки до проверяемого сертификата. доверенная точкаtrust anchor — корневой ключ, которому клиент доверяет заранее и который служит входом для алгоритма проверки пути является входом для алгоритма проверки пути сертификации.
Промежуточные сертификаты образуют звенья цепочки: субъект каждого сертификата является издателем следующего. Первый сертификат в цепочке выдан доверенной точкой, последний — это проверяемый целевой сертификат. Цель всей проверки — подтвердить привязку имени субъекта к открытому ключу на основе открытого ключа доверенной точки.
for all x in {1, ..., n-1}, the subject of certificate x is the issuer of certificate x+1Если доверенная точка представлена самоподписанным сертификатом, он не включается в проверяемый путь. То есть корень не «валидируется» как обычное звено — он задаёт начало отсчёта.
Прозрачность: как сертификат попадает в CT-лог
Certificate TransparencyCT — публичный лог сертификатов, в который CA обязана отправить сертификат до его использования, чтобы любой мог проверить факт выдачи. По RFC 6962 отправители подают сертификаты или Precertificateпредварительный сертификат — версия сертификата, которую лог подписывает до того, как CA поставит финальную подпись в лог и могут использовать возвращённый SCTSigned Certificate Timestamp — подписанное логом подтверждение, что запись принята для построения сертификата или напрямую в TLS-рукопожатии.
PrecertChainцепочка предварительных сертификатов, которую отправитель подаёт в лог отправляется в лог POST-запросом на /ct/v1/add-pre-chain, где chain — массив base64-кодированных предварительных сертификатов, первый элемент — конечный сертификат. SCT — это структура SignedCertificateTimestamp с полями версии, идентификатора лога, метки времени, расширений и подписанной частью. В подписанной части тип записи определяет, что именно подписано: ASN.1Cert для записи x509 или PreCertпредварительный сертификат в том виде, в каком он подписывается логом для записи precert.
struct {
opaque issuer_key_hash[32];
TBSCertificate tbs_certificate;
} PreCert;PreCert содержит SHA-256 хэш публичного ключа издателя и DER-кодированный TBSCertificate без подписи и poison extensionспециальное расширение, которое делает предварительный сертификат непригодным для использования как обычный сертификат. SCT хотя бы от одного лога должен быть включён в TLS-рукопожатие — через расширение сертификата X509v3, TLS-расширение или OCSP Stapling.
Доказательства включения: дерево Меркла
Чтобы доказать, что сертификат действительно попал в лог, используется Merkle audit pathкратчайший список дополнительных узлов дерева Меркла, нужных для вычисления корневого хеша. Если корень, вычисленный по audit path, совпадает с истинным корнем, путь доказывает существование листа в дереве.
Путь задаётся рекурсивно. Для одного листа он пуст. Для n > 1 при k — наибольшей степени двойки, меньшей n, путь строится так:
PATH(m, D[n]) = PATH(m, D[0:k]) : MTH(D[k:n]) for m < k; and
PATH(m, D[n]) = PATH(m - k, D[k:n]) : MTH(D[0:k]) for m >= k,Здесь MTH(D[n]) — [[term:MTH(D[n])|корневой хеш дерева Меркла, построенного по списку листьев D[n]]].
Отдельно применяется Merkle consistency proofдоказательство, что новое дерево содержит старое как префикс — то есть лог только дополняется. Consistency proof доказывает append-only свойство дерева и определяется рекурсивно через SUBPROOF — SUBPROOFвспомогательную рекурсивную процедуру, которая строит consistency proof по префиксу дерева и флагу, указывающему, нужно ли доказывать совпадение с уже известным корнем. Signed Tree Headподписанная логом структура с версией, меткой времени, размером дерева и корневым хешем содержит версию, метку времени, размер дерева и корневой хеш; лог обязан выдавать STH не старше Maximum Merge Delay.
Проверка на практике связывает всё вместе: сертификат с SCT можно проверить против любого STH, датированного после метки времени SCT плюс Maximum Merge Delay, запросив Merkle audit proof. А любую пару STH одного лога можно проверить, запросив consistency proof.
Выдача по ACME: порядок объектов
ACMEпротокол автоматической выдачи сертификатов, стандартизированный в RFC 8555. После регистрации аккаунта клиент выполняет четыре шага: подаёт заказ, доказывает контроль над идентификаторами, финализирует заказ через CSR и получает сертификат.
Orderобъект, представляющий запрос клиента на сертификат и отслеживающий прогресс до выдачи содержит информацию о запрошенном сертификате, требуемых авторизациях и полученных сертификатах. Authorizationобъект, представляющий разрешение сервера аккаунту представлять идентификатор включает статус и информацию о том, какие проверки использовались.
Порядок запросов такой: создание order, получение списка проверок по URL авторизации, ответ на проверки, опрос статуса order, финализация по URL финализации, снова опрос и скачивание сертификата по его URL.
Проверка владения доменом
Поддерживаются два типа проверок: http-01 и dns-01. В http-01 клиент создаёт key authorizationзначение, собранное из token и ключа аккаунта и размещает его на HTTP-сервере домена по пути с фиксированным префиксом /.well-known/acme-challenge/, за которым следует token. Значение ресурса должно быть ASCII-представлением key authorization.
Поскольку домен может разрешаться в несколько адресов IPv4 и IPv6, сервер по своему усмотрению подключается как минимум к одному из хостов, найденных в DNS-записях A и AAAA. Проверка должна выполняться по HTTP, а не HTTPS.
В dns-01 клиент вычисляет SHA-256 от key authorization и помещает base64url-кодирование этого дайджеста в TXT-запись. Имя для проверки строится добавлением метки _acme-challenge к проверяемому домену.
В обоих методах token должен иметь не менее 128 бит энтропии, не содержать символов вне base64url и не включать символы заполнения =.
Защита от повторного воспроизведения
Сервер ведёт список выданных им nonceодноразовое значение, которое клиент обязан вложить в каждый подписанный запрос и требует, чтобы каждый подписанный запрос клиента содержал такое значение. Nonce передаётся в HTTP-заголовке Replay-Nonce; сервер обязан включать его в каждый успешный ответ на POST и должен стараться включать в ответы с ошибкой.
После того как nonce появился в запросе, сервер обязан считать его недействительным так же, как никогда не выданное значение. Если запрос отклонён из-за неприемлемого или отсутствующего nonce, сервер обязан вернуть HTTP-статус 400 и тип ошибки urn:ietf:params:acme:error:badNonce. Такой ответ обязан содержать Replay-Nonce со свежим значением, которое сервер примет при повторной попытке исходного запроса, — клиент повторяет запрос с ним. Если значение параметра nonce не является корректной base64url-строкой, проверяющий обязан отклонить JWS как некорректно сформированный.
Защита ACME-сервера от SSRF и DoS
Чтобы снизить риск SSRFатака, при которой сервер заставляют обратиться к ресурсам внутри его собственной сети, операторам ACME-серверов следует разрешать проверочные запросы только к серверам публичного интернета, а не к внутренним веб-сервисам. Дополнительно рекомендуется выполнять DNS-запросы и HTTP-соединения из нескольких точек сети, чтобы усложнить атаки на маршрутизацию.
От DoS-атакиатака, направленная на исчерпание ресурсов сервера множеством запросов защищают ограничения частоты. При превышении лимита сервер обязан ответить ошибкой типа urn:ietf:params:acme:error:rateLimited и должен отправить заголовок Retry-After, указывающий, когда текущий запрос может снова успешно выполниться. Лимиты могут задаваться по разным ключам — например, по ключу аккаунта или по поддереву DNS. Чтобы злоумышленники не обходили лимиты созданием новых аккаунтов, серверам нужно ограничивать и частоту регистрации аккаунтов.
Имена в сертификатах
Поле issuer идентифицирует организацию, подписавшую и выпустившую сертификат, и обязано содержать непустое distinguished nameDN — иерархическое имя из атрибутов, например country name со значением US. Непустое поле subject тоже содержит X.500 DN, уникальное для каждого субъекта в рамках одного CA, определённого полем issuer. При этом CA может выпустить более одного сертификата с одинаковым DN одному и тому же субъекту.
Если информация об имени субъекта есть только в расширении subjectAltName, то subject обязан быть пустой последовательностью, а subjectAltName — критичным. При кодировании значений DirectoryString соответствующие CA обязаны использовать PrintableString или UTF8String, кроме случаев обратной совместимости с ранее выпущенными TeletexString, BMPString и UniversalString и случаев, когда субъект сам является CA или CRL-издателем — тогда кодировка subject должна совпадать с кодировкой issuer.
Интернационализированные имена поддерживаются через DirectoryString: реализации обязаны поддерживать UTF8String и PrintableString, а поддержка TeletexString, BMPString и UniversalString опциональна. Сравнение атрибутов DN в PrintableString или UTF8String выполняется на основе LDAP StringPrep с обязательной поддержкой caseIgnoreMatch и шестишаговой подготовкой строк. Атрибуты domainComponent сравниваются без учёта регистра, а метки IDN преобразуются через ToASCII.
Отзыв сертификатов
Раздел 6.3 RFC 5280 описывает алгоритм проверки CRL: он определяет, отозван ли сертификат, когда CRLсписок отозванных сертификатов — механизм отзыва, используемый издателем сертификата — это механизм отзыва, используемый издателем сертификата.
Алгоритм принимает на входе сам сертификат (его серийный номер и имя издателя, а также расширения basicConstraints, cRLDistributionPoints и freshestCRL) и булев флаг use-deltas, который решает, применяются ли delta CRLCRL, содержащий только обновления ранее распространённой информации об отзыве к CRL. Состояние отслеживается тремя переменными: набором причин отзыва, покрытых уже обработанными CRL, статусом сертификата (изначально UNREVOKED) и причинами, покрытыми текущим обрабатываемым CRL.
Обработка идёт по каждому distribution point из расширения cRLDistributionPoints и соответствующему CRL в локальном кэше, пока набор причин не станет полным и статус остаётся UNREVOKED. Если текущее время позже next update, при use-deltas и наличии расширения freshest CRL запрашивается delta CRL, иначе обновляется полный CRL. Затем проверяются издатель и область действия CRL, при use-deltas — издатель и область delta CRL, вычисляется промежуточный набор причин, проверяется путь сертификации издателя CRL с тем же доверенным корнем, что и для целевого сертификата, и проверяются подписи CRL и delta CRL. При use-deltas сертификат ищется в delta CRL, и при совпадении издателя и серийного номера статус устанавливается в указанную причину отзыва.
Расширения CRL и как они обрабатываются
CRL Number — некритичное расширение, передающее монотонно возрастающий номер для данного охвата и издателя CRL, позволяя определять, когда один CRL заменяет другой. Издатели, соответствующие профилю, обязаны включать его во все CRL и помечать как некритичное, а верификаторы обязаны обрабатывать значения до 20 октетов.
Delta CRL Indicator — критичное расширение, идентифицирующее CRL как дельта-CRL. Оно содержит одно значение BaseCRLNumber, идентифицирующее полный CRL, использованный как начальная точка. При генерации дельта-CRL издатель обязан включить это критичное расширение.
Issuing Distribution Point — критичное расширение, идентифицирующее точку распространения CRL и охват: покрывает ли CRL только конечные сертификаты, только CA, только атрибутные сертификаты или ограниченный набор кодов причин. Реализации, не поддерживающие это расширение, должны либо считать статус любого не перечисленного сертификата неизвестным, либо найти другой CRL без нераспознанных критичных расширений.
Freshest CRL (также называемое Delta CRL Distribution Point) идентифицирует, как получить информацию дельта-CRL для данного полного CRL. Издатели обязаны помечать его как некритичное, и оно не должно появляться в дельта-CRL.
При обработке для каждой точки распространения алгоритм обновляет локальный кэш CRL, получая полный CRL, дельта-CRL или оба. Если текущее время после next update, use-deltas установлен и либо сертификат, либо CRL содержит freshest CRL, получается дельта-CRL с next update после текущего времени. Если текущее время до next update, use-deltas установлен и freshest CRL присутствует, получается текущий дельта-CRL для обновления уже кэшированного полного CRL.
Постквантовый переход
Вместо конкретных постквантовых алгоритмов подписи описывается переход на Merkle Tree Certificates (MTCMerkle Tree Certificates — новый компактный способ выдачи публично доверенных сертификатов, предназначенный для постквантового мира, где традиционные цепочки сертификатов разрастаются настолько, что нагружают TLS-рукопожатия.). Традиционные цепочки сертификатов в постквантовом мире разрастаются настолько, что начинают перегружать TLS-рукопожатия.
Cloudflare планирует быть одной из первых CA, выпускающих production MTC, с первыми сертификатами в первом квартале 2027 года. Переход не будет внезапным: значительная часть интернета ещё много лет продолжит полагаться на классические сертификаты и существующий WebPKI, но доля MTC будет постепенно расти.
Чтобы избежать жёсткого переключения, один сервис CA будет обслуживать и классические сертификаты, и MTC — с одним жизненным циклом и одним набором гарантий. Клиентам не придётся выбирать сторону многодесятилетней миграции, запускать две системы или перестраиваться при смещении баланса. Совместимость со старыми клиентами при этом обеспечивает приобретённый корень GlobalSign, а новый корень рассчитан на будущие политики экосистемы.
Прозрачность эксплуатации
CA планирует публиковать воспроизводимые сборки подписывающего ПО, аттестовать HSM с ключами и вести публичный дашборд состояния выдачи и инцидентов.
Что из этого следует на практике
- Один корень не решает задачу целиком. Новый корень годами не дойдёт до устройств, переставших обновляться, поэтому покупка уже доверенного корня — не запасной вариант, а необходимое условие охвата старых клиентов с первого дня.
- Автоматизация продления становится условием выдачи, а не рекомендацией. Клиент без поддержки ARI не получит сертификат. Это цена за возможность сдвигать окна продления и распределять замены при отзыве.
- Проверка сертификата — это путь от доверенной точки, а не проверка одного сертификата. Самоподписанный корень в путь не входит; цепочка строится от него как от входа.
- SCT нужно предъявить в рукопожатии. Факта записи в лог недостаточно — подтверждение хотя бы от одного лога должно быть доставлено клиенту через расширение сертификата, TLS-расширение или OCSP Stapling.
- Проверка владения доменом недетерминирована при нескольких адресах. Сервер сам выбирает, к какому из хостов из записей A и AAAA подключиться, и делает это по HTTP, а не HTTPS.
- Отзыв по CRL — многошаговый алгоритм с состоянием. Статус складывается из нескольких CRL и delta CRL, а не определяется одним списком; расширения вроде Issuing Distribution Point меняют охват и требуют либо считать статус неизвестным, либо искать другой CRL.
- Переход на постквантовые сертификаты не будет переключателем. Классические и MTC-сертификаты будут сосуществовать в одном CA с одним жизненным циклом, чтобы миграция шла в темпе клиента.