JEP 249: OCSP Stapling for TLS
OCSP stapling для TLS
| Ответственный | Jamil Nimeh |
| Тип | Feature |
| Область | SE |
| Статус | Closed / Delivered |
| Выпуск | 9 |
| Компонент | security-libs / javax.net.ssl |
| Обсуждение | security dash dev at openjdk dot java dot net |
| Трудоёмкость | M |
| Длительность | M |
| Рецензенты | Brian Goetz, Sean Mullan |
| Одобрен | Brian Goetz |
| Создан | 2014/06/09 07:30 |
| Обновлён | 2026/07/29 18:45 |
| Задача | 8046321 |
Аннотация
Реализовать OCSP stapling с помощью расширения TLS Certificate Status Request (раздел 8 RFC 6066) и расширения Multiple Certificate Status Request (RFC 6961).
Критерии успеха
Реализация как в клиентском, так и в серверном режиме должна успешно взаимодействовать как минимум с двумя сторонними реализациями TLS, поддерживающими OCSP stapling.
Мотивация
Проверка статуса отзыва сертификата X.509 — критически важная часть корректной аутентификации на основе сертификатов. Однако проверка статуса сертификата с помощью OCSP обычно требует сетевого запроса для каждого проверяемого сертификата. Из-за дополнительных сетевых запросов включение проверки OCSP для TLS на стороне клиента может существенно сказаться на производительности.
OCSP stapling позволяет, чтобы расходы ресурсов на предоставление OCSP-ответов нёс тот, кто предъявляет сертификат, а не выпустивший его удостоверяющий центр (Certificate Authority, CA). В контексте TLS за запрос OCSP-ответа и его отправку клиентам во время рукопожатия SSL/TLS отвечает TLS-сервер. Кроме того, сервер может кэшировать OCSP-ответы и передавать их всем подключающимся к нему клиентам. Это значительно снижает нагрузку на OCSP-респондер, поскольку ответ может кэшироваться и периодически обновляться сервером, а не каждым клиентом.
Сейчас проверку статуса отзыва сертификатов можно включить на стороне клиента. Однако у этого классического подхода есть ряд проблем:
Производительность
Если клиент получает статус отзыва непосредственно от OCSP-респондера, то для каждого клиента, подключающегося к определённому серверу, OCSP-респондер должен вернуть ответ с конкретным статусом сертификата. Для сайта с высокой посещаемостью OCSP-респондер, скорее всего, станет узким местом по производительности. Кроме того, проверка статуса отзыва включает несколько циклов обмена запросом и ответом. Если проверка OCSP включена на стороне клиента, это существенно сказывается на производительности.
Безопасность
Adam Langley в одной из записей своего блога рассказывает о проблемах безопасности, с которыми сталкиваются клиентские приложения при традиционном OCSP. Он описывает поведение «soft-fail» (мягкий отказ), реализованное в большинстве браузеров: политику, при которой неудачная попытка связаться с OCSP-респондером не приводит к провалу проверки отзыва. Из-за этого злоумышленник может заставить клиента обойти проверку отзыва — перехватив или заблокировав OCSP-запрос клиента либо проведя атаку типа «отказ в обслуживании» на сам респондер.
Сам по себе OCSP stapling не устраняет эту проблему полностью, но избавляет от необходимости проверок OCSP между клиентом и респондером. Сервер по-прежнему должен иметь возможность получить собственный OCSP-ответ и передать его внутри канала (in-band) в рамках рукопожатия TLS.
Сейчас в IETF в виде черновика находится предложение о расширении сертификата «must-staple», которое требовало бы прикладывать OCSP-ответ во время рукопожатия TLS. По сути, это отменяло бы любое поведение soft-fail, которое может применять клиент. Это предлагаемое расширение выходит за рамки данного JEP, но если оно перестанет быть черновиком, то в будущем может стать полезным дополнением.
Наконец, Java-клиентам не обязательно нужны те же значения soft-fail по умолчанию, что и браузерам. В некоторых случаях клиенты могут предпочесть подход hard-fail (жёсткий отказ) или получать отклик пользователя через диалоговое окно, если OCSP-ответ получить не удалось. Например, подход soft-fail по умолчанию и в Java Plugin, и в Java Web Start состоит в показе диалогового окна с предупреждением при загрузке подписанных апплетов.
Возможное нарушение конфиденциальности при OCSP-запросах
В обычных сценариях OCSP клиент, отправляя OCSP-запрос, раскрывает OCSP-респондеру и сервер (через запись о сертификате сервера), и себя (как минимум через IP-адрес) и, следовательно, может раскрыть поведение клиента. OCSP stapling решает эту проблему, поскольку клиент больше не отправляет запрос OCSP-респондеру.
Ограничения техники «captive portal»
Техника «captive portal» заставляет HTTP-клиента в сети загрузить специальную веб-страницу, обычно для аутентификации, прежде чем он сможет нормально пользоваться сетью. В таких средах клиенты не могут проверить OCSP-статус сертификата SSL/TLS, поскольку весь сетевой доступ заблокирован до успешной аутентификации.
Итоги
Перечисленные проблемы можно частично смягчить с помощью CRL или лучше решить с помощью OCSP stapling.
Итак, OCSP stapling может помочь повысить производительность TLS, устраняя узкое место в виде OCSP-респондера. Он также может предотвратить возможное нарушение конфиденциальности при OCSP-запросе и обойти ограничение техники «captive portal».
Описание
Эта возможность будет реализована в провайдере SunJSSE. Запланированы небольшие изменения API, и цель — свести эти изменения к минимуму. Реализация выберет разумные значения по умолчанию для параметров, специфичных для OCSP, и позволит настраивать эти значения через следующие системные свойства:
jdk.tls.client.enableStatusRequestExtension: по умолчанию это свойство равно true. Оно включает расширенияstatus_requestиstatus_request_v2, а также обработку сообщенийCertificateStatus, отправляемых сервером.jdk.tls.server.enableStatusRequestExtension: по умолчанию это свойство равно false. Оно включает поддержку OCSP stapling на стороне сервера.jdk.tls.stapling.responseTimeout: это свойство задаёт максимальное время, которое сервер потратит на получение OCSP-ответов — из кэша или обращаясь к OCSP-респондеру. Полученные ответы будут отправлены в сообщении CertificateStatus, если это применимо с учётом используемого типа stapling. Свойство принимает целое значение в миллисекундах, значение по умолчанию — 5000.jdk.tls.stapling.cacheSize: это свойство задаёт максимальный размер кэша в записях. Значение по умолчанию — 256 объектов. Если кэш заполнен и нужно закэшировать новый ответ, запись кэша, которая дольше всех не использовалась, будет заменена новой. Значение ноль или меньше означает, что количество ответов, которые может содержать кэш, не ограничено сверху.jdk.tls.stapling.cacheLifetime: это свойство задаёт максимальное время жизни закэшированного ответа. Значение указывается в секундах, по умолчанию — 3600 (1 час). Время жизни ответа может оказаться короче значения этого свойства, если в ответе есть поле nextUpdate, срок которого истекает раньше срока жизни в кэше. Значение ноль или меньше отключает ограничение времени жизни в кэше. Если у объекта нет nextUpdate, а время жизни в кэше отключено, ответ не будет кэшироваться.jdk.tls.stapling.responderURI: это свойство позволяет администратору задать URI по умолчанию на случай, если у сертификатов, используемых для TLS, нет расширения Authority Info Access. Оно не переопределяет значение расширения AIA, если не задано свойство jdk.tls.stapling.responderOverride (см. ниже). По умолчанию это свойство не задано.jdk.tls.stapling.responderOverride: это свойство позволяет URI, заданному через свойство jdk.tls.stapling.responderURI, переопределять любое значение расширения AIA. По умолчанию оно равно false.jdk.tls.stapling.ignoreExtensions: это свойство отключает пересылку расширений OCSP, указанных в TLS-расширенияхstatus_requestилиstatus_request_v2. По умолчанию оно равно false.
Реализации Java на стороне клиента и сервера смогут поддерживать hello-расширения TLS status_request и status_request_v2. Расширение status_request описано в RFC 6066. Поддерживающие его серверы будут включать один OCSP-ответ для сертификата, идентифицирующего сервер, в новое сообщение рукопожатия TLS (CertificateStatus). Расширение status_request_v2 описано в RFC 6961. Оно позволяет клиенту запросить у сервера один OCSP-ответ в сообщении CertificateStatus (аналогично status_request) или попросить сервер получить OCSP-ответ для каждого сертификата из списка сертификатов в сообщении Certificate (далее — тип ocsp_multi).
Клиентская сторона
-
OCSP stapling будет включён по умолчанию, и его можно отключить с помощью системного свойства. Это делается через свойство
jdk.tls.client.enableStatusRequestExtension. -
По умолчанию клиенты будут указывать в сообщении рукопожатия
ClientHelloоба расширения —status_requestиstatus_request_v2. Для расширенияstatus_request_v2будут указываться оба типа —ocspиocsp_multi. -
Для создания hello-расширений потребуется создать новые классы в
sun.security.ssl— по аналогии с тем, как были реализованыServerNameIndicator,RenegotiationInfoExtensionи другие расширения. -
Чтобы использовать новые расширения, в классе
ClientHelloбудут определены дополнительные методы, добавляющие эти расширения. Эти методы будут вызываться изClientHandshaker.clientHello(). -
Потребуется создать новый класс сообщения рукопожатия в классе
HandshakeMessageдля кодирования и разбора сообщенияCertificateStatus. -
Необходимо изменение публичного API в
ExtendedSSLSession, позволяющее вызывающему коду получать OCSP-ответы, полученные в процессе рукопожатия. Новый метод:public List<byte[]> getStatusResponses();
Серверная сторона
-
В реализации на стороне сервера OCSP stapling по умолчанию будет отключён, но его можно включить с помощью системного свойства
jdk.tls.server.enableStatusRequestExtension. Серверы с отключённой поддержкой OCSP stapling будут игнорировать расширенияstatus_requestиstatus_request_v2. -
Заполнение сервером информации
status_requestилиstatus_request_v2в сообщенииServerHelloбудет зависеть от того, как клиент указал эти расширения. Как правило, то же расширение запроса, что было вClientHello, будет возвращено вServerHello, за следующими исключениями:-
Серверы, получившие в
ClientHelloоба расширения —status_requestиstatus_request_v2, — будут указыватьstatus_request_v2вServerHello. -
Серверы, получившие в
ClientHelloрасширенияstatus_request_v2с обоими типамиocspиocsp_multi, будут указыватьstatus_request_v2в сообщенииServerHelloиocsp_multiв сообщенииCertificateStatus. -
Если выбран
status_request_v2/ocsp_multi, для получения каждого ответа будут использоваться разные потоки. Этим будет управлятьStatusResponseManager, который отвечает и за получение, и за кэширование OCSP-ответов.
-
-
OCSP-ответы следует кэшировать везде, где это возможно. Клиенты, не указывающие nonce в своём расширении
status_request[_v2], могут получить закэшированный ответ.-
Закэшированные ответы не следует использовать, если текущее время позже значения поля
nextUpdate. -
Закэшированные ответы без поля
nextUpdateмогут храниться в кэше в течение заранее заданного времени жизни (см. «Настраиваемые параметры» ниже). -
Серверы, получившие
status_requestsс расширением nonce, не должны возвращать закэшированные ответы в сообщенииCertificateStatus.
-
-
Поддержку stapling на стороне сервера можно будет настраивать через описанные выше системные свойства.
-
StatusResponseManagerсоздаётся при создании экземпляраSSLContext. Значения свойств считываются при конструированииSSLContext. Эти значения можно изменить, и когда будет создан новый объектSSLContext, StatusResponseManager получит новые значения.
Stapling и X509ExtendedTrustManagers
У разработчиков есть определённая свобода в том, как обрабатывать ответы, полученные через OCSP stapling. Этот JEP не меняет существующие методики проверки пути сертификации и проверки отзыва. Это значит, что и клиент, и сервер могут указывать расширения status_request, получать OCSP-ответы через сообщение CertificateStatus и оставлять пользователю свободу в том, как реагировать на информацию об отзыве или на её отсутствие.
Как и в предыдущих выпусках JDK, если вызывающий код не передаёт PKIXBuilderParameters, проверка отзыва отключена. Если вызывающий код создаёт PKIXBuilderParameters и включает проверку отзыва методом setRevocationEnabled, то OCSP-ответы, полученные через stapling, будут проверяться. То же самое происходит, если свойство com.sun.net.ssl.checkRevocation имеет значение true. В таблице ниже приведены примеры нескольких подходов (предполагается, что OCSP stapling включён и на клиенте, и на сервере):
| PKIXBuilderParameters | Свойство checkRevocation | PKIXRevocationChecker | Результат |
|---|---|---|---|
| по умолчанию | по умолчанию | по умолчанию | Проверка отзыва отключена |
| по умолчанию | true | по умолчанию | Проверка отзыва включена*, установлен SOFT_FAIL |
| создан экземпляр | по умолчанию | по умолчанию | Проверка отзыва включена*, установлен SOFT_FAIL |
| создан экземпляр | по умолчанию | создан экземпляр, добавлен в PKIXBuilderParameters | Проверка отзыва включена*, режим hard fail (жёсткий отказ). |
* Клиент выполнит собственный OCSP-запрос в качестве запасного варианта, только если свойство безопасности ocsp.enable установлено в true
Подробнее о настройке объектов PKIXBuilderParameters и PKIXRevocationChecker и об их связи с JSSE можно узнать в Java PKI API Programmer's Guide и в JSSE Reference Guide.
Тестирование
-
Реализация OCSP Stapling не должна нарушать обратную совместимость.
-
Клиентская реализация должна уметь отправлять серверам, которые их поддерживают, расширения
status_requestClientHelloв стиле RFC 6066. Она должна правильно разбирать то же hello-расширение в сообщении рукопожатияServerHelloи правильно разбирать содержимое последующего сообщения рукопожатияCertificateStatus. -
Клиентская реализация должна уметь отправлять серверам, которые их поддерживают, расширения
status_request_v2ClientHelloв стиле RFC 6961. Она должна уметь указывать в hello-расширении типыocspилиocsp_multi(или оба). Она должна правильно разбирать те же hello-расширения в сообщении рукопожатияServerHelloи правильно разбирать содержимое последующего сообщения рукопожатияCertificateStatus. -
Серверная реализация должна уметь принимать расширения
status_requestиstatus_request_v2в сообщении рукопожатияClientHelloи запрашивать соответствующий OCSP-респондер. Она должна уметь помещать OCSP-ответы в сообщение рукопожатия TLSCertificateStatus, которое возвращается клиенту. -
Серверная реализация должна уметь кэшировать действительные OCSP-ответы для повторного использования с клиентами, которые не передают расширения nonce в своих hello-расширениях
status_request[_v2]. -
Клиент должен взаимодействовать как минимум с двумя разными веб-серверами, поддерживающими OCSP stapling (например, Apache 2.4+).
-
Сервер должен взаимодействовать как минимум с двумя разными клиентскими реализациями, способными указывать
status_requestилиstatus_request_v2. В настоящее время большинство основных браузеров (Firefox, Chrome и др.) умеют формировать hello-расширениеstatus_request, как и другие инструменты, напримерs_clientиз OpenSSL. Для автоматического тестирования можно создать небольшие приложения, которые компонуются с библиотеками NSS и OpenSSL и устанавливают TLS-соединения с OCSP stapling.
Риски и допущения
В этой реализации OCSP stapling будет по умолчанию включён для клиентов Java в JDK. Однако возможны проблемы совместимости с TLS-серверами, которые не принимают расширения TLS status_request или status_request_v2. Чтобы при необходимости отключить OCSP stapling, определено системное свойство или свойство безопасности.