INTEGRITY Документация

Передача сертификата на сервер

Добавление заголовков Client-Cert и Client-Cert-Chain (RFC 9440)

RFC 9440 определяет Client-Cert и Client-Cert-Chain Поля HTTP-заголовков для передачи информации о клиентском сертификате на исходный сервер. Эти заголовки можно сформировать с помощью правила изменения заголовков запроса со следующими полями Ruleset Engine:

Как указано в определениях полей, поля могут быть заданы либо как пустая строка, либо как корректная кодировка RFC 9440. Правильное использование зависит от нескольких факторов, которые рассматриваются в следующих разделах.

Соображения по безопасности

cert_rfc9440 и cert_chain_rfc9440 поля заполняются независимо от результата проверки сертификата. Это означает, что клиент может предоставить недействительный, просроченный или самоподписанный сертификат, а поля всё равно будут содержать закодированные данные сертификата. Прежде чем доверять значениям, всегда проверяйте следующие поля:

Клиент также может включить собственный Client-Cert или Client-Cert-Chain заголовки в запросе, чтобы внедрить произвольные значения. Как описано в Соображения безопасности RFC 9440, вы должны безусловно удалить все существующие Client-Cert и Client-Cert-Chain заголовки из входящих запросов независимо от действительности сертификата. Это не даёт клиенту внедрить поддельные данные сертификата, которым доверял бы ваш источник.

См. Включение mTLS для сведений о настройке mTLS и проверки сертификатов.

Ограничения по размеру

Закодированный конечный сертификат ограничен 10 KiB, а закодированная цепочка ограничена 16 KiB. Если закодированное значение превышает лимит, соответствующее поле содержит пустую строку. Чтобы проверить это условие, используйте следующие поля:

Примеры Transform Rules

Здесь мы приводим пример того, как безопасно использовать эти поля для формирования доверенного Client-Cert и Client-Cert-Chain заголовки для пересылки на ваш источник. После этого источник может полагаться на наличие заголовков, чтобы убедиться, что клиент предоставил действительный сертификат. Примечание: Client-Cert-Chain заголовок может отсутствовать, если клиент не предоставил промежуточные сертификаты (только конечный сертификат).

Вам нужно создать следующие правила изменения заголовков запроса. Заголовок Удалить правила должны быть размещены перед Включить динамический режим правила, чтобы заголовки, добавленные клиентом, удалялись при каждом запросе до установки проверенных значений.

Правило 1. Удаление заголовка Client-Cert

Это правило безусловно удаляет любой Client-Cert заголовок, отправленный клиентом.

Текст в Expression Editor:

true

Выбранная операция в разделе Изменить заголовок запроса: Удалить

Имя заголовка: Client-Cert

Правило 2. Удаление заголовка Client-Cert-Chain

Это правило безусловно удаляет любой Client-Cert-Chain заголовок, отправленный клиентом.

Текст в Expression Editor:

true

Выбранная операция в разделе Изменить заголовок запроса: Удалить

Имя заголовка: Client-Cert-Chain

Правило 3. Установка заголовка Client-Cert

Это правило задаёт Client-Cert заголовок только тогда, когда клиент предоставил действительный, неотозванный сертификат, не превышающий ограничение по размеру.

Текст в Expression Editor:

cf.tls_client_auth.cert_verified
and not cf.tls_client_auth.cert_revoked
and not cf.tls_client_auth.cert_rfc9440_too_large

Выбранная операция в разделе Изменить заголовок запроса: Включить динамический режим

Имя заголовка: Client-Cert

Значение: cf.tls_client_auth.cert_rfc9440

Правило 4. Установка заголовка Client-Cert-Chain

Это правило задаёт Client-Cert-Chain заголовок только тогда, когда клиент предоставил действительный, неотозванный сертификат, а цепочка не пуста и не превышает ограничение по размеру.

Текст в Expression Editor:

cf.tls_client_auth.cert_verified
and not cf.tls_client_auth.cert_revoked
and cf.tls_client_auth.cert_chain_rfc9440 ne ""
and not cf.tls_client_auth.cert_chain_rfc9440_too_large

Выбранная операция в разделе Изменить заголовок запроса: Включить динамический режим

Имя заголовка: Client-Cert-Chain

Значение: cf.tls_client_auth.cert_chain_rfc9440

Cloudflare Workers

Вы также можете сформировать заголовки RFC 9440 в Cloudflare Worker с использованием tlsClientAuth свойства во входящем запросе.

Действуют те же соображения безопасности, что указаны выше.

Передача клиентского сертификата (устаревший способ)

Помимо принудительной mTLS-аутентификации для вашего хоста, вы также можете передавать клиентский сертификат на исходный сервер в виде HTTP-заголовка. Это часто полезно для журналирования на сервере.

Чтобы не добавлять сертификат к каждому запросу, он передаётся только с первым запросом mTLS-соединения.

Cloudflare API

Наиболее распространённый способ переслать сертификат: использовать API Cloudflare, чтобы обновить настройки имени узла сертификата mTLS.

Необходимые разрешения API-токена

Хотя бы одно из следующих права доступа токена требуется:
Изменение настроек имени хоста сертификата mTLS
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/access/certificates/settings" \
	--request PUT \
	--header "X-Auth-Email: $CLOUDFLARE_EMAIL" \
	--header "X-Auth-Key: $CLOUDFLARE_API_KEY" \
	--json '{
		"settings": [
				{
						"hostname": "<HOSTNAME>",
						"china_network": false,
						"client_certificate_forwarding": true
				}
		]
	}'

Как только client_certificate_forwarding имеет значение true, теперь каждый запрос в рамках mTLS-соединения будет включать следующие заголовки:

Managed Transforms

Вы также можете изменять заголовки HTTP-ответов с помощью Managed Transforms, чтобы передать Заголовки клиентской аутентификации TLS.

Cloudflare Workers

Кроме того, Workers могут предоставлять сведения о клиентский сертификат.

const tlsHeaders = {
	"X-CERT-ISSUER-DN": request.cf.tlsClientAuth.certIssuerDN,
	"X-CERT-SUBJECT-DN": request.cf.tlsClientAuth.certSubjectDN,
	"X-CERT-ISSUER-DN-L": request.cf.tlsClientAuth.certIssuerDNLegacy,
	"X-CERT-SUBJECT-DN-L": request.cf.tlsClientAuth.certSubjectDNLegacy,
	"X-CERT-SERIAL": request.cf.tlsClientAuth.certSerial,
	"X-CERT-FINGER": request.cf.tlsClientAuth.certFingerprintSHA1,
	"X-CERT-VERIFY": request.cf.tlsClientAuth.certVerify,
	"X-CERT-NOTBE": request.cf.tlsClientAuth.certNotBefore,
	"X-CERT-NOTAF": request.cf.tlsClientAuth.certNotAfter,
};