New certificates missing TLS ciphers

I'm in the process of migrating a Debian 10 server that's a couple years old to Debian 12. One thing that was causing some issues was ensuring that TLS 1.0 was working properly on the new server. After changing SECLEVEL from 1 to 0, though, I was able to get openssl s_client to work with Apache.

However, the client devices I was testing are still failing to negotiate TLS on that server. Curious, I tried basically everything I could to see what was different, and what I discovered was if I copied over the Let's Encrypt certificate from the old server to the new server, it would work. However, if I requested a new certificate on the new server, it would fail. I thought it might be because I was using acme.sh on the new server instead of certbot, to avoid all the snapd bloat, but I set up a brand new server with certbot to test and according to nmap, the ciphers are missing on both.

Here's what I get on the new server:

| ssl-enum-ciphers:
|   TLSv1.0:
|     ciphers:
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A
|     compressors:
|       NULL
|     cipher preference: server

However, if I copy over the certificate from the old server, I get something more reasonable:

| ssl-enum-ciphers:
|   TLSv1.0:
|     ciphers:
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 2048) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (dh 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 2048) - A
|       TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (dh 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
|     compressors:
|       NULL
|     cipher preference: server

I enabled cipher logging in Apache on the old system to confirm the cipher that the client was using, and it's TLSv1 DHE-RSA-AES256-SHA, which I believe corresponds to TLS_DHE_RSA_WITH_AES_256_CBC_SHA, which as you can see, is missing in the output on the new server.

At this point, it seems like it's an issue with the Let's Encrypt certificates themselves, given that's the only issue.

I'm wondering is there some difference here where new certificate requests are getting these deficient certificates, but the renewals on the old server are still getting all the ciphers that are needed? If so, how can I ensure that a certificate on the new server has the missing ciphers? I could use the old cert for now, but obviously that's only good for 3 months and then it will need to renew.

I suspect what’s happening is that the new certificate is an ECDSA certificate instead of RSA. You can tell because of the _ECDSA_ instead of _RSA_ in the cipher suite names.

Certbot switched to ECDSA by default for new installs in version 2.0. Existing installs stay on RSA for renewals but you’re on a new server, it might have changed.

ECDSA is generally well supported today, but if you’re requiring 1.0 then I assume you’re using some old devices which don’t support modern TLS features. It’s also possible they support ECDSA with a cipher you don’t have enabled on your server. It’s hard to know without a list of supported ciphers from your clients.

You could consider requesting RSA certs manually, though if you’ve copied over the certs from the old server, certbot renew will get new RSA certs automatically.

9 Likes

https://eff-certbot.readthedocs.io/en/stable/using.html#changing-a-certificate-s-key-type

5 Likes

acme.sh also defaults to ECDSA since version 3.0.6

5 Likes

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