These clients used to verify certificate chains in a bad way, here's a short explanation:
Older versions of OpenSSL, GnuTLS (+ many others, e.g LibreSSL) basically validate a certificate chain by walking up the chain as send by the server, then searching the trust store for the "highest" certificate. That means those clients always validate up the highest certificate in the chain.
This is an issue, as Let's Encrypt is going to send a chain that ends with DST Root CA X3, which expires later this year. This means that those clients will fail, as they no longer consider the highest root a trusted certificate.
The correct way to verify the certificate chain is by looking at the intermediates: In the chain send by Let's Encrypt certificates, there's an intermediate "ISRG Root X1 signed by DST Root CA X3" that is in fact a root in itself. If a chain verifier realizes this, it can stop verifying at ISRG Root X1 and does not need to verify the expired DST Root CA X3 cert.
Older versions of many non-browser verifiers sadly do not have this feature, and will sadly fail handshakes.
The OpenSSL fix to this issue was the introduction of a new flag X509_V_FLAG_TRUSTED_FIRST
. If a client application sets this flag, it causes OpenSSL to search the trust store before processing the intermediate. This causes OpenSSL to stop looking at the chain when ISRG Root X1 is encountered, preventing issues with an expired DST Root CA X3.
This flag is available since OpenSSL 1.0.2 (must be manually requested by the application using OpenSSL) and is set by default since OpenSSL 1.1+, which is why that version is considered fixed.
Yes, altough the initial description is highly confusing.
Let's Encrypt has already started to use the new chain (since May 4), but it isn't causing issues yet, as DST Root CA X3 is not yet expired. You can't test using production, as Let's Encrypt certificates are only valid for 90 days, but the expiry is more than 90 days away.
You can however test using the staging enviroment, quoting myself: