The TLS handshake is failing because the client doesn’t trust the server’s certificate.

Common Causes and Fixes

1. Expired Certificate

  • Diagnosis: Check the certificate’s expiration date on the server.
    openssl x509 -in /etc/ssl/certs/your_domain.crt -noout -dates
    
  • Fix: Renew the certificate with your Certificate Authority (CA). For example, if using Let’s Encrypt, run:
    sudo certbot renew
    sudo systemctl reload nginx # or apache2ctl graceful
    
  • Why it works: A certificate is only valid for a specific period. Once expired, it’s no longer trusted by clients. Renewing it issues a new, valid certificate.

2. Incorrect Certificate Chain (Missing Intermediate Certificates)

  • Diagnosis: Use openssl s_client to inspect the certificate chain presented by the server.
    openssl s_client -connect your_domain.com:443 -servername your_domain.com </dev/null | openssl x509 -noout -text | grep "Issuer:"
    
    Compare the issuer with the CA’s intermediate certificate bundle.
  • Fix: Concatenate the server certificate, any necessary intermediate certificates, and the root CA certificate into a single file (often named fullchain.pem or similar) and configure your web server to use this file. For Nginx:
    ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
    
    For Apache:
    SSLCertificateFile /etc/letsencrypt/live/your_domain.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/your_domain.com/privkey.pem
    
  • Why it works: Browsers and clients need to trace the certificate’s authenticity back to a trusted root CA. If intermediate certificates are missing, the client can’t complete this chain of trust.

3. Certificate Issued to the Wrong Domain Name (Hostname Mismatch)

  • Diagnosis: Check the "Subject Alternative Name" (SAN) or "Common Name" (CN) field of the certificate.
    openssl x509 -in /etc/ssl/certs/your_domain.crt -noout -text | grep -A 1 'Subject Alternative Name'
    
    Ensure the domain you’re accessing (your_domain.com) is listed.
  • Fix: Reissue the certificate from your CA, ensuring all required domain names (including www.your_domain.com if applicable) are included in the request. Then, update your web server configuration to point to the new certificate and key files.
  • Why it works: TLS relies on verifying that the certificate presented matches the hostname the client is trying to connect to. If they don’t match, the connection is considered insecure.

4. Server Not Presenting the Correct Certificate File

  • Diagnosis: Use openssl s_client to see which certificate the server is actually serving.
    openssl s_client -connect your_domain.com:443 -servername your_domain.com </dev/null | openssl x509 -noout -subject
    
    Compare the output subject with the expected certificate.
  • Fix: Verify your web server’s SSL configuration points to the correct certificate and private key files. For example, in Nginx:
    ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
    
    Reload your web server after changes: sudo systemctl reload nginx.
  • Why it works: The web server might be configured to use an old, expired, or incorrect certificate file, even if a valid one exists on the system.

5. Client-Side Trust Issues (Less Common for Browsers, More for Services)

  • Diagnosis: If a specific client service is failing, check its trust store. For example, on a Linux client:
    openssl s_client -connect your_domain.com:443 -servername your_domain.com </dev/null | openssl x509 -noout -issuer
    
    Verify the issuer is in the client’s trusted CA bundle (e.g., /etc/ssl/certs/ca-certificates.crt).
  • Fix: If the issuing CA is not trusted by the client, you may need to manually add the CA’s root certificate to the client’s trust store. For Debian/Ubuntu:
    sudo cp your_ca_root.crt /usr/local/share/ca-certificates/
    sudo update-ca-certificates
    
  • Why it works: The client needs to trust the Certificate Authority that signed the server’s certificate. If the root CA is missing from the client’s local trust store, it cannot validate the certificate.

6. Certificate Revocation Issues (CRL/OCSP)

  • Diagnosis: Some clients may check Certificate Revocation Lists (CRLs) or Online Certificate Status Protocol (OCSP) responses. If the CA’s revocation servers are unreachable or the certificate is listed as revoked, this error can occur. This is harder to diagnose directly without client logs.
  • Fix: This is usually a problem with the CA or the network path to the CA’s revocation servers. Ensure your server is configured to provide OCSP stapling if possible, which can improve performance and reliability. For Nginx:
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/your_domain.com/chain.pem; # Often chain.pem or fullchain.pem
    resolver 8.8.8.8 8.8.4.4 valid=300s; # Use your preferred DNS resolvers
    resolver_timeout 10s;
    
  • Why it works: OCSP stapling allows the server to proactively fetch and present the revocation status of its own certificate to clients during the handshake, reducing reliance on the client reaching the CA’s revocation servers directly.

The next error you might encounter is an "SSL_ERROR_RX_RECORD_TOO_LONG" if the TLS configuration is fundamentally broken or if there’s a proxy interfering with the handshake.

Want structured learning?

Take the full Tls-ssl course →