RFC 9440 ↗ 定义了 Client-Cert 和 Client-Cert-Chain HTTP 标头字段,用于将客户端证书信息传递给源站服务器。你可以使用请求标头修改规则和以下 Ruleset Engine 字段构造这些标头:
cf.tls_client_auth.cert_rfc9440— 以 RFC 9440 格式编码的客户端叶证书(见参考)。cf.tls_client_auth.cert_chain_rfc9440— 以 RFC 9440 格式编码的证书链(不含叶证书)(见参考)。
如字段定义所示,这些字段可设为空字符串或有效的 RFC 9440 编码。正确用法取决于以下各节讨论的几个因素。
无论证书验证结果如何,cert_rfc9440 和 cert_chain_rfc9440 字段都会被填充。这意味着客户端可以出示无效、过期或自签名证书,字段仍会包含编码的证书数据。在信任这些值之前,务必检查以下字段:
cf.tls_client_auth.cert_verified— 客户端证书有效时返回true。cf.tls_client_auth.cert_revoked— 客户端证书已被吊销时返回true。
客户端还可能在请求中包含自己的 Client-Cert 或 Client-Cert-Chain 标头以注入任意值。如 RFC 9440 安全注意事项 ↗ 所述,你必须无条件移除入站请求中任何现有的 Client-Cert 和 Client-Cert-Chain 标头,无论证书是否有效。这可防止客户端注入源站会信任的伪造证书数据。
有关如何配置 mTLS 和证书验证的详情,请参阅启用 mTLS。
编码的叶证书限制为 10 KiB,编码的证书链限制为 16 KiB。若编码值超出限制,对应字段将包含空字符串。使用以下字段检查此情况:
cf.tls_client_auth.cert_rfc9440_too_large— 编码证书超过 10 KiB 时返回true。cf.tls_client_auth.cert_chain_rfc9440_too_large— 编码证书链超过 16 KiB 时返回true。
以下示例说明如何安全使用这些字段构造可信的 Client-Cert 和 Client-Cert-Chain 标头并转发到源站。
源站随后可依赖这些标头的存在,确信客户端出示了有效证书。
注意:当客户端未提供任何中间证书(仅叶证书)时,可省略 Client-Cert-Chain 标头。
你需要创建以下请求标头修改规则。 Remove 规则必须放在 Set dynamic 规则之前, 以便在设置已验证的值之前,在每个请求上剥离客户端注入的标头。
此规则无条件移除客户端发送的任何 Client-Cert 标头。
Expression Editor(表达式编辑器) 中的文本:
trueModify request header(修改请求标头) 下选择的操作:Remove
Header name(标头名称):Client-Cert
此规则无条件移除客户端发送的任何 Client-Cert-Chain 标头。
Expression Editor(表达式编辑器) 中的文本:
trueModify request header(修改请求标头) 下选择的操作:Remove
Header name(标头名称):Client-Cert-Chain
此规则仅在客户端出示有效、未吊销且在大小限制内的证书时设置 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_largeModify request header(修改请求标头) 下选择的操作:Set dynamic
Header name(标头名称):Client-Cert
Value(值):cf.tls_client_auth.cert_rfc9440
此规则仅在客户端出示有效、未吊销的证书,
且证书链非空并在大小限制内时设置 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_largeModify request header(修改请求标头) 下选择的操作:Set dynamic
Header name(标头名称):Client-Cert-Chain
Value(值):cf.tls_client_auth.cert_chain_rfc9440
你也可以在 Cloudflare Worker 中使用入站请求上的 tlsClientAuth 属性构造 RFC 9440 标头。
上述相同的安全注意事项同样适用。
除为主机强制执行 mTLS 认证外,您还可以将客户端证书作为 HTTP 标头转发到源站服务器。此设置通常有助于服务器日志记录。
为避免在每个请求中添加证书,证书仅在 mTLS 连接的第一个请求上转发。
转发证书的最常见方法是使用 Cloudflare API 更新 mTLS 证书的主机名设置。
Required API token permissions
At least one of the following token permissions is required:Access: Mutual TLS Certificates Write
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 连接内的每个请求现在将包含以下标头:
Cf-Client-Cert-Der-Base64Cf-Client-Cert-Sha256
您还可以使用 Managed Transforms 修改 HTTP 响应标头,以传递 TLS client auth headers。
此外,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,
};