Linux – Self signed certificate not trusted

certificatehttpslinuxsslUbuntu

I have created my own CA:

openssl genrsa -out private/rootCA.key 2048
openssl req -batch -new -x509 -nodes -key private/rootCA.key -sha256 -days 1024 -config ./openssl.conf -out certs/rootCA.pem

I have created a certificate for my site:

openssl genrsa -out private/$domain.key 2048
openssl req -batch -new -key private/$domain.key -config ./openssl.conf -subj "/commonName=$domain" -out csr/$domain.csr
openssl x509 -req -in csr/$domain.csr -CA certs/rootCA.pem -CAkey private/rootCA.key -CAcreateserial -out certs/$domain.crt -days 500 -sha256

I join the site cert and the root cert into a bundle:

cat certs/$domain.crt certs/rootCA.pem > bundles/$domain.bundle.crt

I copy the cert / key to the nginx config dir:

cp bundles/$domain.bundle.crt private/$domain.key /etc/nginx/conf/certs

I make sure that nginx uses those certs for my site:

    ssl_certificate /etc/nginx/certs/mysite.bundle.crt;
    ssl_certificate_key /etc/nginx/certs/mysite.key;

I restart nginx.

I install the root cert in my system:

sudo cp certs/rootCA.pem /usr/local/share/ca-certificates/myrootCA.crt
sudo update-ca-certificates

I verify with httpie:

» http https://mysite

http: error: SSLError: HTTPSConnectionPool(host='mysite', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",),))

I verify with openssl (telling it to use the ca-certificates dir, which is not used by default it seems):

openssl s_client -host mysite -port 443 -prexit -showcerts -CApath /usr/local/share/ca-certificates

Which gives:

Verify return code: 19 (self signed certificate in certificate chain)

And verification does not complete.

Opening the site in Chrome gives me the standard error:

This server could not prove that it is mysite; its security
certificate is not trusted by your computer's operating system. This
may be caused by a misconfiguration or an attacker intercepting your
connection.

I have two questions:

  1. Why is the site not trusted, system-wide, after installing the root cert? Chrome is using system-wide cerficates, right?
  2. Why is open_ssl s_client not able to complete the cert validation?

EDIT

Curl is working, with the system-wide installed cert:

curl https://mysite

Why is curl working and chrome/httpie not?

Best Answer

For OpenSSL Ubuntu update-ca-certificates as described on its man page reads from /usr/share/ca-certificates AND /usr/local/share/ca-certificates but writes symlinks with the subjhash.num names needed by OpenSSL to /etc/ssl/certs and a combined file in /etc/ssl/certs/ca-certificates.crt so the latter two should be used with -CApath and/or -CAfile respectively.

curl apparently uses the OpenSSL default, which in this build is /etc/ssl/certs/, but depending on which Ubuntu, OpenSSL may be old enough to have the bug that commandline s_client does NOT use the default automatically.

For Chrome I can't help; I don't use Chrome on Ubuntu. Left CW in case someone else can.

Although I do know once you get the CA trusted, recent Chrome also requires your server cert (in PKI terms, End Entity = EE = not CA) have a SAN extension (SubjectAlternateNames) with the correct name(s), which neither of the others do (for now), and you don't indicate if/how you did that. (expanded:) rfc 2818 for HTTPS and the CABforum standards have for over a decade required server certs to contain valid SAN, and by now all or nearly all clients use SAN when present, but to my knowledge so far Chrome is the only client that requires SAN be present.

Related Question