2

I'm having some difficulty with nginx's client authentication while using an intermediate CA (self-created).

Although the same certificate bundle (intermediate + root certificates in a single .pem file) works just fine for client authentication in IMAP (dovecot) and SMTP (postfix), I just can't seem to get it to work with nginx. Instead I'm getting the following error:

[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>"

As I understand it, an error type 27 from openssl is X509_V_ERR_CERT_UNTRUSTED, or some kind of issue with a certificate being untrusted for a particular purpose, however I can't get it to elaborate any further.

The individual and bundled certificates all seem to validate correctly with openssl verify (I can verify client certificates against intermediate or the bundle, and the intermediate certificate validates against the root certificate, i.e- it's all valid in every combination I can think of).

My root and intermediate CAs should be set with the correct extensions in order to verify my client certificates, here's the relevant sample of my custom openssl.conf file:

[ 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

Meanwhile the client certificates that I'm issuing are configured to work for both client authentication and e-mail encryption/signing like so:

[ 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

(indeed, if they weren't set correctly then OS X's Safari and Mail wouldn't let me send them at all, as they tend to be really strict).

A number of similar questions have recommended setting ssl_verify_depth to a value of 2 (to verify both the intermediate and root certificates), but this doesn't seem to help.

  • How have you configured client auth in nginx? And how have you tested that? Because from your question that seems to be what is broken and your apparent conclusion that it should be the certificate(s) might be a bit premature... – HBruijn Feb 22 '16 at 16:19
  • Sorry I forgot to mention; I know the nginx configuration is correct as it was working previously using a simpler root certificate I created for testing that has now expired. I'm now trying to use the recommended root + intermediate style chain of authentication, but although the certificates look valid to me nginx doesn't seem to accept them when a valid client connects. – Haravikk Feb 23 '16 at 19:39
  • Could you provide the nginx configuration you are using, for completeness? – Castaglia Mar 12 '16 at 16:37
  • I'm in the exact same situation as @Haravikk. The nginx configuration was working with a previous set of certs, but those used a simplified hierarchy (root signing everything) and now I'm moving to the more traditional hierarchy (root signing intermediates that sign end certs). Here's a snip of my nginx config (limited by comment length): ssl on; ssl_certificate /etc/ssl/custom/my.cert; ssl_certificate_key /etc/ssl/custom/my.key; ssl_client_certificate /etc/ssl/custom/clientchain.pem; ssl_verify_client on; ssl_verify_depth 1; – lcarsos Mar 14 '16 at 20:43
4

I have the same setup, and have been trying to diagnose this exact issue. The certs worked just fine on an apache instance, but nginx was being a problem. This is the solution I've come up with.

Point your ssl_client_certificate at your root certificate. Not your intermediate. Then also ensure that nginx verifies to a depth of 2. I've tried having a certificate chain file as the paramater for the client certificate, and it still didn't work. I don't understand why it has to be the root, instead of the intermediate that signed the cert. But this works.

For completeness, here's what the relevant parts of my nginx configuration look like:

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>;
}
  • 1
    Setting the ssl_verify_depth to 2 fixed it for me. Even with the intermediate certificates contained in the file specified by ssl_client_certificate. – Florian Apr 5 '17 at 10:02
  • Not your intermediate. <-- THIS. I spent hours figuring this out. Thank you. – StampyCode Feb 13 '18 at 13:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.