Remote 'openssl s_client' verification of LE cert reports "self-signed"; same check of Comodo cert reports correctly?


#1

I’m writing a script for automating reissue & rollover of ECDSA LE certs, since certbot doesn’t provide that automation.

I’ve generated an LE ec cert.

It’s installed on my website.

Browser visit to it works.

Firefox gives it its “green” cert-verified indicator

The cert reports in the browser as

Certification path for "example.com"
Subject: CN=example.com
Issuer: C=US,O=Let's Encrypt,CN=Let's Encrypt Authority X3
Validity: from Wed 03 Aug 2016 03:14:00 PM EST UTC to Tue 01 Nov 2016 03:14:00 PM EST UTC
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
Subject: C=US,O=Let's Encrypt,CN=Let's Encrypt Authority X3
Issuer: O=Digital Signature Trust Co.,CN=DST Root CA X3
Validity: from Thu 17 Mar 2016 04:40:46 PM PST UTC to Wed 17 Mar 2021 04:40:46 PM PST UTC
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
Subject: O=Digital Signature Trust Co.,CN=DST Root CA X3
Issuer: O=Digital Signature Trust Co.,CN=DST Root CA X3
Validity: from Sat 30 Sep 2000 09:12:19 PM PST UTC to Thu 30 Sep 2021 02:01:15 PM PST UTC
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

and SSLLabs gives it an “A+”.

Also checking locally with openssl shows a valid cert date

openssl x509 -enddate -noout -in cert.pem
        notAfter=Nov  1 00:14:00 2016 GMT

So all looks OK.

But checking remotely via openssl s_client

echo | openssl s_client -connect example.com:443 -CApath /etc/ssl/certs | openssl x509 -noout -dates

Returns a ‘self-signed’ cert, with dates that don’t relate at all to my server/certs

depth=0 C = US, ST = CA, L = San Francisco Bay Area, O = local / self-signed, CN = local / self-signed
verify error:num=18:self signed certificate
verify return:1
depth=0 C = US, ST = CA, L = San Francisco Bay Area, O = local / self-signed, CN = local / self-signed
verify return:1
DONE
notBefore=Jan 11 01:40:37 2014 GMT
notAfter=Jan  9 01:40:37 2024 GMT

OTOH, the same remote check, to a different domain on the same server,

echo | openssl s_client -connect example2.com:443 -CApath /etc/ssl/certs | openssl x509 -noout -dates

using a Comodo-generated commercial RSA cert returns correct information – both that it’s a commercial, NOT-self-signed cert, and with correct Validity dates

depth=3 C = SE, O = AddTrust AB, OU = AddTrust External TTP Network, CN = AddTrust External CA Root
verify return:1
depth=2 C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO RSA Certification Authority
verify return:1
depth=1 C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO RSA Domain Validation Secure Server CA
verify return:1
depth=0 OU = Domain Control Validated, OU = EssentialSSL Wildcard, CN = *.example2.com
verify return:1
DONE
notBefore=Sep  1 00:00:00 2015 GMT
notAfter=Oct 21 23:59:59 2016 GMT

Why does the LE cert verify remotely as self-signed, but the Comodo cert verifies correctly?


#2

Any chance your web server is configured with both an ECDSA and a RSA cert, and the RSA one happens to be the self-signed certificate you’re seeing there? Maybe some leftovers somewhere in your config.

Web servers that implement this hybrid setup typically select the certificate based on the cipher suites the client offers. If openssl s_client doesn’t offer any ECDSA suites (not sure if this is the case), the web server will use the RSA certificate. Firefox offers ECDSA suites, so that’s probably why you’re getting the correct certificate there.

Anyhow, independent of what the underlying issue is, that certificate does not look remotely like anything Let’s Encrypt would issue, so you’re probably better off focusing your search on areas that are not specific to Let’s Encrypt.


#3

You might need to add -servername example2.com in your OpenSSL command. Unlike browsers, the s_client doesn’t send SNI information by default, I believe, and your web server might be choosing which certificate to return based on SNI.


#4

You might need to add -servername example2.com in your OpenSSL command.

Yep. I’d just found & tested

Now, it’s correctly reporting

echo | openssl s_client -connect example.com:443 -servername example.com

...
    Certificate chain
     0 s:/CN=example.com
       i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
     1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
       i:/O=Digital Signature Trust Co./CN=DST Root CA X3
...
    depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
    verify return:1
    depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
    verify return:1
    depth=0 CN = example.com
    verify return:1
    DONE
    notBefore=Aug  5 17:04:00 2016 GMT
    notAfter=Nov  3 17:04:00 2016 GMT
...

Absolutely no idea yet why it works for the Comodo-cert’d domain, and not for this one. Suspect it’s just luck in some sort of prioritization by nginx.


#5

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.