HAProxy is terminating TLS connections and then forwarding the decrypted HTTP traffic to your backend servers.
The Problem: TLS Handshake Failures
HAProxy is failing to establish a TLS connection with the client, meaning your users can’t reach your service. This happens because HAProxy can’t complete the handshake process, which involves exchanging certificates and agreeing on encryption parameters.
Common Causes and Fixes
-
Expired Certificate:
- Diagnosis:
Look foropenssl x509 -in /etc/ssl/certs/your_domain.crt -noout -datesnotBeforeandnotAfterdates. IfnotAfteris in the past, the certificate is expired. - Fix: Obtain a new certificate from your Certificate Authority (CA) and replace the existing files (e.g.,
your_domain.crt,your_domain.key).# Example: Replace old files with new ones mv /etc/ssl/certs/your_domain.crt /etc/ssl/certs/your_domain.crt.old mv /etc/ssl/certs/your_domain.key /etc/ssl/certs/your_domain.key.old cp /path/to/new/your_domain.crt /etc/ssl/certs/your_domain.crt cp /path/to/new/your_domain.key /etc/ssl/certs/your_domain.key chmod 600 /etc/ssl/certs/your_domain.key - Why it works: The client’s browser or tool explicitly checks the validity period of the certificate. An expired certificate is untrustworthy, and the handshake will fail immediately.
- Diagnosis:
-
Incorrect Certificate/Key Pair:
- Diagnosis: HAProxy logs might show errors like
SSL handshake failedorcertificate verification failed. Manually check if the private key matches the certificate.
The MD5 hashes should match.openssl x509 -noout -modulus -in /etc/ssl/certs/your_domain.crt | openssl md5 openssl rsa -noout -modulus -in /etc/ssl/certs/your_domain.key | openssl md5 - Fix: Ensure the
crtandkeyfiles specified in your HAProxy configuration (crtdirective) are the correct, corresponding pair.
If they don’t match, correct thefrontend http_frontend bind *:443 ssl crt /etc/ssl/certs/your_domain.crt # ... other frontend configcrtandkeypaths or replace them with the correct files. - Why it works: The server must prove it possesses the private key corresponding to the public key in the certificate. If they don’t match, the server can’t perform the necessary cryptographic operations to authenticate itself.
- Diagnosis: HAProxy logs might show errors like
-
Missing Intermediate Certificates (Chain Issues):
- Diagnosis: Clients might report "certificate chain is incomplete" or similar errors. A manual check with
openssl s_clientcan reveal this.
Examine theopenssl s_client -connect your_domain.com:443 -servername your_domain.com < /dev/nullCertificate chainsection. If it only shows your server certificate and not the CA’s intermediate certificates, there’s a problem. - Fix: Concatenate your server certificate with its intermediate certificates into a single file, ordered correctly (server cert first, then intermediates).
Update your HAProxy configuration to point to this newcat your_domain.crt intermediate_ca.crt > your_domain_fullchain.crtyour_domain_fullchain.crtfile.frontend http_frontend bind *:443 ssl crt /etc/ssl/certs/your_domain_fullchain.crt # ... - Why it works: Browsers and clients need to trust the entire chain of certificates back to a trusted root CA. If intermediates are missing, the client can’t verify the authenticity of your server certificate.
- Diagnosis: Clients might report "certificate chain is incomplete" or similar errors. A manual check with
-
Incorrect Permissions on Certificate/Key Files:
- Diagnosis: HAProxy logs will often show errors like
permission deniedorcannot open file. - Fix: Ensure the HAProxy process (usually running as user
haproxyornginx) has read permissions on both the certificate and private key files. The private key should ideally only be readable by the HAProxy user.chown haproxy:haproxy /etc/ssl/certs/your_domain.crt chown haproxy:haproxy /etc/ssl/certs/your_domain.key chmod 640 /etc/ssl/certs/your_domain.key # Only readable by owner and group chmod 644 /etc/ssl/certs/your_domain.crt # Readable by all - Why it works: HAProxy needs to read the certificate and private key to perform the TLS handshake. If it lacks the necessary permissions, it cannot access these critical files.
- Diagnosis: HAProxy logs will often show errors like
-
Incorrect SSL Configuration in HAProxy:
- Diagnosis: Generic
SSL handshake failederrors in HAProxy logs, especially after configuration changes. - Fix: Review your
bindline for SSL/TLS. Ensure thesslkeyword is present and thecrtpath is correct. Check for typos or incorrect directives.
If you’re using client certificates (frontend http_frontend bind *:443 ssl crt /etc/ssl/certs/your_domain.crt ca-file /etc/ssl/certs/ca-bundle.crt mode http default_backend http_backendca-fileorverify required), ensure those files are also correctly specified and accessible. - Why it works: The
binddirective is how HAProxy listens for incoming connections and what protocols it expects. An improperly configuredbindline will prevent HAProxy from correctly initiating or responding to TLS connections.
- Diagnosis: Generic
-
Protocol/Cipher Mismatch:
- Diagnosis: HAProxy logs might indicate "unsupported protocol" or "no common cipher." Clients might report "unsupported_cipher_suite."
- Fix: Configure HAProxy to support modern TLS versions and a secure set of ciphers. Use
ssl-default-bind-ciphersandssl-default-bind-optionsdirectives.frontend http_frontend bind *:443 ssl crt /etc/ssl/certs/your_domain.crt \ ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets mode http default_backend http_backend - Why it works: Both the client and the server must agree on a TLS protocol version and a cipher suite for encryption. If they don’t have any common options, the handshake fails. This ensures compatibility and security.
After resolving TLS handshake issues, you’ll likely encounter problems with HAProxy forwarding traffic to your backend servers, such as 503 Service Unavailable errors.