How to Fix Apache Load Balancer SSL Handshake Errors with Backend Servers (Self-Signed Certificates)


2 views

When configuring Apache (2.4+) as a load balancer with HTTPS backends, you might encounter SSL handshake failures even with proper SSLProxyEngine settings. Here's a deep dive into solving this common infrastructure challenge.

The error typically manifests in Apache logs with messages like:

[proxy:error] AH01084: pass request body failed to backend:443
[proxy:error] AH00898: Error during SSL Handshake with remote server

Browser responses show:

Proxy Error
Reason: Error during SSL Handshake with remote server

For modern Apache versions (2.4.5+), these directives are essential:

SSLProxyEngine on
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off  # Crucial for newer Apache versions

Here's a production-tested configuration for a load-balanced cluster:

<VirtualHost *:443>
    SSLEngine on
    SSLCertificateFile /path/to/cert.pem
    SSLCertificateKeyFile /path/to/key.pem
    
    SSLProxyEngine on
    SSLProxyVerify none
    SSLProxyCheckPeerCN off
    SSLProxyCheckPeerName off
    
    <Proxy balancer://secure-cluster>
        BalancerMember https://backend1.example.com:443 route=node1
        BalancerMember https://backend2.example.com:443 route=node2
        ProxySet stickysession=ROUTEID
    </Proxy>
    
    ProxyPass / balancer://secure-cluster/
    ProxyPassReverse / balancer://secure-cluster/
</VirtualHost>

While the solution works with self-signed certificates, consider these practices:

  • Ensure consistent DNS naming in your infrastructure
  • For production, use properly signed certificates or internal CA
  • Test with OpenSSL directly: openssl s_client -connect backend:443 -servername backend.example.com

If issues persist:

  1. Verify backend SSL configuration independently
  2. Check Apache error logs with LogLevel debug temporarily
  3. Test with curl: curl -v -k https://backend/test.jsp
  4. Verify TCP connectivity: telnet backend 443

Terminating SSL at both layers adds overhead. Consider:

  • HTTP/2 between load balancer and backends if supported
  • Session resumption configuration
  • OCSP stapling implementation

When configuring Apache 2.4 as a load balancer with HTTPS backends, you might encounter this frustrating scenario: HTTP backends work perfectly, but HTTPS connections fail with mysterious 502 errors and SSL handshake failures. Let's dissect this common issue that many sysadmins face when dealing with self-signed certificates in backend servers.

The error logs typically show these telltale signs:

[proxy:error] AH01084: pass request body failed to backend:443
[proxy:error] AH00898: Error during SSL Handshake with remote server
[proxy_http:error] AH01097: pass request body failed to backend:443

While the browser displays the unhelpful but accurate "Proxy Error" message indicating SSL Handshake failure with the remote server.

After extensive troubleshooting, the core issue emerges: certificate name verification. Even with SSLProxyVerify none configured, Apache 2.4.5+ performs additional checks:

  • Certificate Common Name (CN) must match the backend server name
  • Subject Alternative Names (SANs) are also verified

For Apache 2.4.7+ configurations, you need these critical directives:

SSLProxyEngine on
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off

<Proxy balancer://securecluster>
  BalancerMember https://backend1:443/test
  BalancerMember https://backend2:443/test
  ProxySet lbmethod=bytraffic
</Proxy>
ProxyPass /test balancer://securecluster
ProxyPassReverse /test balancer://securecluster

When working with self-signed certificates:

  1. Always test direct connections to backends first using openssl s_client -connect backend:443
  2. For production environments, consider proper certificates or configure SSLProxyCACertificateFile
  3. Monitor connection states with server-status module

For complex setups with sticky sessions:

<Proxy balancer://stickycluster>
  BalancerMember https://backend1:443/test route=node1
  BalancerMember https://backend2:443/test route=node2
  ProxySet stickysession=ROUTEID lbmethod=byrequests
</Proxy>

ProxyPass /test balancer://stickycluster
Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED

Remember to restart Apache after configuration changes and always check apachectl configtest before applying changes to production environments.