DEV Community

Deep Fix
Deep Fix

Posted on

Fix SSL/TLS Certificate Handshake Failures – Step‑by‑Step Guide for Developers

Introduction

A TLS handshake failure is one of the most frustrating errors you can encounter when deploying web services. Whether you see SSL handshake failed, certificate verify failed, or a generic ERR_SSL_PROTOCOL_ERROR, the underlying cause is usually a mis‑configuration of certificates, protocol versions, or trust stores. This guide walks you through the most common culprits and provides concrete, reproducible steps to get your connections working again.

Common Causes

  • Expired or revoked certificate – The leaf certificate is no longer valid.
  • Incomplete certificate chain – Intermediate certificates are missing on the server.
  • Hostname mismatch – The CN/SAN does not match the request host.
  • Unsupported TLS version or cipher suite – Client and server cannot agree on a common set.
  • Out‑of‑date trust store – The client does not trust the issuing CA.

Step‑by‑Step Troubleshooting

1. Inspect the Server Certificate Chain

# Replace example.com with your host
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null 2>/dev/null | openssl x509 -noout -text
Enter fullscreen mode Exit fullscreen mode

Look for the Certificate chain section. All intermediate certificates must be presented by the server. If any are missing, add them to your server config (e.g., fullchain.pem for Nginx/Apache).

2. Verify Hostname Matching

import ssl, socket
hostname = "example.com"
ctx = ssl.create_default_context()
with ctx.wrap_socket(socket.socket(), server_hostname=hostname) as s:
    s.connect((hostname, 443))
    cert = s.getpeercert()
    print(cert["subjectAltName"])
Enter fullscreen mode Exit fullscreen mode

If the output does not contain your hostname, re‑issue the certificate with the correct Subject Alternative Name.

3. Update the Trusted Root Store

Linux (Debian/Ubuntu)

sudo apt-get update && sudo apt-get install --reinstall ca-certificates
sudo update-ca-certificates
Enter fullscreen mode Exit fullscreen mode

Windows PowerShell

Get-ChildItem Cert:\LocalMachine\Root | Where-Object {$_.Subject -match "YourCA"} | Remove-Item
Import-Certificate -FilePath "C:\path\to\YourCA.crt" -CertStoreLocation Cert:\LocalMachine\Root
Enter fullscreen mode Exit fullscreen mode

4. Force a Compatible TLS Version / Cipher Suite

Nginx

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
Enter fullscreen mode Exit fullscreen mode

Apache

SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite HIGH:!aNULL:!MD5
Enter fullscreen mode Exit fullscreen mode

Restart the web server after changes.

5. Use Diagnostic Tools

  • Wireshark – Capture the TLS handshake and look for Alert messages.
  • curl – Add -v or --tlsv1.2 to see detailed handshake logs.
  • testssl.sh – Comprehensive SSL/TLS testing script.

Example Fix Script

The following Bash script automates the most common fixes (chain concatenation, store update, and service reload). Feel free to adapt it to your environment.

#!/usr/bin/env bash
set -euo pipefail

HOST=$1
CERT_DIR="/etc/ssl/certs"
CHAIN_FILE="${CERT_DIR}/${HOST}.fullchain.pem"
LEAF_CERT="${CERT_DIR}/${HOST}.crt"
INTERMEDIATE="${CERT_DIR}/${HOST}.intermediate.pem"

# 1. Combine leaf + intermediate certificates
cat "$LEAF_CERT" "$INTERMEDIATE" > "$CHAIN_FILE"

echo "[+] Combined certificate chain saved to $CHAIN_FILE"

# 2. Update trust store (Debian/Ubuntu example)
sudo apt-get install -y ca-certificates
sudo update-ca-certificates

echo "[+] Trust store refreshed"

# 3. Reload web server (detect Nginx or Apache)
if systemctl -q is-active nginx; then
  sudo systemctl reload nginx
  echo "[+] Nginx reloaded"
elif systemctl -q is-active apache2; then
  sudo systemctl reload apache2
  echo "[+] Apache reloaded"
else
  echo "[!] No supported web server detected"
fi
Enter fullscreen mode Exit fullscreen mode

You can download the pre‑configured script here: Download the pre‑configured script here.

Quick Recap

  1. Check the chain with openssl s_client.
  2. Validate hostname using a tiny Python snippet.
  3. Refresh trust stores on both client and server.
  4. Align TLS versions and cipher suites in your web server config.
  5. Leverage tools like curl -v, Wireshark, or testssl.sh for deeper inspection.

If you prefer an all‑in‑one solution, Get the complete patch tool from our repository: Get the complete patch tool.

For a broader context and additional hardening tips, Access the full repository fix here: Access the full repository fix.

Top comments (0)