客户端 SSL 证书验证错误:(27:证书不受信任)

客户端 SSL 证书验证错误:(27:证书不受信任)

在使用中间 CA(自行创建)时,我在 nginx 的客户端身份验证方面遇到了一些困难。

尽管相同的证书包(单个 .pem 文件中的中间证书 + 根证书)在 IMAP(dovecot)和 SMTP(postfix)中可以很好地用于客户端身份验证,但我似乎无法让它与 nginx 配合使用。相反,我收到以下错误:

[info] 23383#23383: *14583139 client SSL certificate verify error: (27:certificate not trusted) while reading client request headers, client: 82.39.81.156, server: <hostname>, request: "GET /mailboxes HTTP/1.1", host: "<hostname>"

据我了解,openssl 的错误类型 27 是X509_V_ERR_CERT_UNTRUSTED,或者是证书因特定目的而不受信任的某种问题,但我无法进一步详细说明。

单个证书和捆绑证书似乎都经过了正确验证openssl verify(我可以根据中间证书或捆绑证书来验证客户端证书,并且中间证书可以根据根证书来验证,即,在我能想到的每种组合中它都是有效的)。

我的根 CA 和中级 CA 应设置正确的扩展名以验证我的客户端证书,这是我的自定义openssl.conf文件的相关示例:

[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always,issuer
basicConstraints        = critical, CA:true
keyUsage                = critical, digitalSignature, cRLSign, keyCertSign

[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always,issuer
basicConstraints        = critical, CA:true, pathlen:0
keyUsage                = critical, digitalSignature, cRLSign, keyCertSign

同时,我颁发的客户端证书配置为用于客户端身份验证和电子邮件加密/签名,如下所示:

[ user_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints        = CA:FALSE
nsCertType              = client, email
nsComment               = "OpenSSL Generated Client Certificate"
subjectAltName          = email:move
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid,issuer
keyUsage                = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage        = critical, clientAuth, emailProtection

(事实上​​,如果它们设置不正确,那么 OS X 的 Safari 和 Mail 根本不会让我发送它们,因为它们往往非常严格)。

许多类似的问题建议将其设置ssl_verify_depth为值 2(以验证中间证书和根证书),但这似乎没有帮助。

答案1

我有相同的设置,并一直在尝试诊断这个确切的问题。证书在 Apache 实例上运行良好,但 nginx 存在问题。这是我想到的解决方案。

指向你ssl_client_certificate的根证书。而不是你的中间证书。然后还要确保 nginx 验证深度为 2。我尝试将证书链文件作为客户端证书的参数,但仍然不起作用。我不明白为什么作为根,而不是签署证书的中间人。但这是可行的。

为了完整起见,我的 nginx 配置的相关部分如下:

server {
    listen 8443 ssl;
    server_name               www.example.com;

    ssl                       on;
    ssl_certificate           /path/to/cert.pem;
    ssl_certificate_key       /path/to/key.key;
    ssl_client_certificate    /path/to/root.ca.cert;
    ssl_verify_client         on;
    ssl_verify_depth          2;
    ssl_protocols             TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers               <snipped-for-length>;
}

相关内容