TLS 1.0 – Issues with Newer Debian and OpenSSL

apache-2.4opensslssl

I'm migrating a server running Debian 10 to a server running Debian 12 (and a 6.x kernel), and the last thing that doesn't seem to be working is TLS 1.0, which I've been trying to figure out.

I'm aware of changing the SECLEVEL and MinProtocol as described here: https://stackoverflow.com/a/61568390/6110631, but this hasn't worked, for some reason.

On the working system, I have:

[system_default_sect]
MinProtocol = TLSv1.0
CipherString = ALL:@SECLEVEL=1

I tried adding this in the same manner on the new system, but TLS 1.0 still doesn't seem to work. In the Apache server (which is depending application), I can see:

AH02039: Certificate Verification: Error (68): CA signature digest algorithm too weak

I somewhat expected this, as I figured TLS 1.0 would be disabled by default, so I toyed with the config further. No changes I made seemed to work, and doing packet captures from the client perspective via a port mirror, I could see that all TLS negotiation was failing outright (right after Client Hello, Alert (Level: Fatal, Description: Protocol Version).

Probing with openssl s_client, it seems that something is very broken with TLS 1.0 altogether.

On the existing Debian 10 server, I get:

# openssl version
OpenSSL 1.1.1n  15 Mar 2022

# openssl s_client -connect OLDHOST -tls1
CONNECTED(00000003)
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = OLDHOST
verify return:1
---
Certificate chain
 0 s:CN = OLDHOST
   i:C = US, O = Let's Encrypt, CN = R3
 1 s:C = US, O = Let's Encrypt, CN = R3
   i:C = US, O = Internet Security Research Group, CN = ISRG Root X1
 2 s:C = US, O = Internet Security Research Group, CN = ISRG Root X1
   i:O = Digital Signature Trust Co., CN = DST Root CA X3
---
Server certificate
-----BEGIN CERTIFICATE-----

However, on the new Debian 12 server, I get:

# openssl version
OpenSSL 3.0.9 30 May 2023 (Library: OpenSSL 3.0.9 30 May 2023)

# openssl s_client -connect NEWHOST -tls1
CONNECTED(00000003)
140101680407744:error:14094438:SSL routines:ssl3_read_bytes:tlsv1 alert internal error:../ssl/record/rec_layer_s3.c:1544:SSL alert number 80
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 136 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1
    Cipher    : 0000
    Session-ID:
    Session-ID-ctx:
    Master-Key:
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1695085443
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
    Extended master secret: no

TLS 1.2 still works correctly, but I get this for TLS 1.0 and TLS 1.1.

I've tried using DEFAULT:@SECLEVEL=1, ALL:@SECLEVEL=1 and other combinations of sec level 1, sec level 0, ALL, DEFAULT, LEGACY, etc. None of them seems to work. I've been regularly restarting Apache and the entire server between changes.

I've also tried adding that to the Apache config, so I have the following:

Protocols h2 http/1.1
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite ALL:@SECLEVEL=0
SSLHonorCipherOrder on
SSLCompression off
SSLSessionTickets off

Other related questions/answers, that unfortunately haven't yielded any more insight:

A few places do seem to imply that nowadays, you have to lower SECLEVEL from 1 to 0 to get this to work, e.g. for SHA1 certs, which I've done, but no cigar still.

TLS 1.0 and 1.1 support has not been removed in OpenSSL 3 (I did check), so it should be supported, with the proper configuration.

All the documented solutions don't seem to be working for me, and I don't seem to be any closer after wasting the whole day debugging this. Is there any other solution anyone has found for getting older ciphers to work? I'm specifying ALL ciphers and at both levels 0 and 1, and it doesn't seem to be obeying me, so this seems rather bizarre.

Best Answer

I knew this was possible, and likely a configuration snafu... indeed, that's what it was.

Setting the SECLEVEL to 0 is indeed necessary, but I had this in multiple places, and hadn't updated it in all of them.

In particular, the specific virtualhost still had SSLCipherSuite ALL:@SECLEVEL=1, which worked fine with older OpenSSL versions, but this now needs to be SSLCipherSuite ALL:@SECLEVEL=0.

(I had set this in the general Apache config as well as in /etc/ssl/openssl.cf`, but since this was set at the virtualhost level, it was overriding that. All the other virtualhosts happened to be at level 0 already, and I just happened to be testing using the one virtualhost that was overridden to 1, naturally...)

I do want to iterate that people who say that TLS 1.0 is not supported with recent kernels, Apache, or OpenSSL (such as in a comment to this question) are wrong and they do work with correct configuration. This seems to be a common misconception.

Currently, the end client is still not connecting (TLS handshake failure), so something is still off, but openssl s_client now negotiates properly, unlike before, which is progress.

The full solution was also realizing that both certbot and acme.sh by default now prefer ECDSA and so you need to explicitly request RSA to get the missing ciphers. The old server "worked" fine because the certs were renewing of the same type.

Snippet from openssl.cnf on new, working system:

cat /etc/ssl/openssl.cnf | grep -v "#"

openssl_conf = openssl_init

[openssl_init]
providers = provider_sect
ssl_conf = ssl_sect

[ssl_sect]
system_default = system_default_sect

[system_default_sect]
MinProtocol = TLSv1.0
CipherString = ALL@SECLEVEL=0