How to Fix HAProxy 502 Bad Gateway: HTTP Spoken on HTTPS Port Error


5 views

When working with HAProxy 1.5.8 and Apache 2.2, I encountered this frustrating error where HTTPS requests would result in 502 Bad Gateway errors. The Apache logs clearly showed:

[debug] ssl_engine_kernel.c(1903): OpenSSL: Exit: error in SSLv2/v3 read client hello A
[info] [client haproxy-server] SSL handshake failed: HTTP spoken on HTTPS port
[info] SSL Library Error: 336027804 error:1407609C:SSL routines:SSL23_GET_CLIENT_HELLO:http request

The key issue here is that HAProxy is forwarding decrypted HTTP traffic to Apache's HTTPS port (443), while Apache expects encrypted traffic on that port. This creates a protocol mismatch.

Here's the problematic HAProxy config I started with:

frontend FT-https-in
  bind *:443 ssl crt /etc/haproxy/ssl/my_cert.pem
  default_backend BK-https-out

backend BK-https-out
  server myserver-https x.x.x.x:443 check

The fix involves either:

  1. Terminating SSL at HAProxy and sending plain HTTP to Apache
  2. Maintaining SSL all the way through (SSL passthrough)

Option 1: SSL Termination at HAProxy

This is the simpler approach:

frontend FT-https-in
  bind *:443 ssl crt /etc/haproxy/ssl/my_cert.pem
  default_backend BK-http

backend BK-http
  server myserver-http x.x.x.x:80 check

Then configure Apache to listen on port 80 for this traffic.

Option 2: SSL Passthrough

For end-to-end encryption:

frontend FT-https-in
  bind *:443
  mode tcp
  default_backend BK-https-passthrough

backend BK-https-passthrough
  mode tcp
  server myserver-https x.x.x.x:443 check
  • When using SSL termination, ensure your backend server expects HTTP traffic
  • For passthrough, both frontend and backend must be in TCP mode
  • Certificate bundles should follow the correct order: certificate, private key, intermediate certificates

If issues persist:

# Debug SSL handshake
openssl s_client -connect yourdomain.com:443 -showcerts

# Verify HAProxy SSL configuration
haproxy -c -f /etc/haproxy/haproxy.cfg

# Check Apache SSL module loading
apachectl -M | grep ssl

When working with HAProxy 1.5.8 and Apache 2.2 configurations, one particularly frustrating error occurs when the backend server complains about HTTP traffic reaching its HTTPS port. The Apache error log clearly states:

[Thu Aug 13 17:02:38 2015] [info] [client haproxy-server] SSL handshake failed: HTTP spoken on HTTPS port
[Thu Aug 13 17:02:38 2015] [info] SSL Library Error: 336027804 error:1407609C:SSL routines:SSL23_GET_CLIENT_HELLO:http request

The fundamental issue stems from a misconfiguration in SSL termination. HAProxy is terminating SSL at the frontend but not properly converting the traffic when forwarding to the backend Apache server. The current configuration shows:

frontend FT-https-in
    bind *:443 ssl crt /etc/haproxy/ssl/my_cert.pem
    # ... other settings ...
    default_backend BK-https-out

backend BK-https-out
    server myserver-https x.x.x.x:443 check

This setup attempts to forward SSL-terminated traffic over another HTTPS connection to the backend, which creates protocol conflicts.

The correct approach involves either:

Option 1: Complete SSL termination (HAProxy handles all SSL, backend communicates via HTTP)

frontend FT-https-in
    bind *:443 ssl crt /etc/haproxy/ssl/my_cert.pem
    default_backend BK-http-out

backend BK-http-out
    server myserver-http x.x.x.x:80 check

Option 2: SSL passthrough (HAProxy doesn't terminate SSL)

frontend FT-https-in
    bind *:443
    mode tcp
    default_backend BK-https-passthrough

backend BK-https-passthrough
    mode tcp
    server myserver-https x.x.x.x:443 check

For complete SSL termination (Option 1), these headers help maintain protocol information:

http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
http-request set-header X-SSL %[ssl_fc]

For Apache configuration, ensure these directives exist:

SetEnvIf X-Forwarded-Proto https HTTPS=on
RemoteIPHeader X-Forwarded-For

When using PEM files with HAProxy, the correct format is:

-----BEGIN CERTIFICATE-----
[Your Primary SSL Certificate]
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
[Your Private Key]
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
[Intermediate Certificate]
-----END CERTIFICATE-----

Use these HAProxy debugging techniques:

# Check SSL handshake
openssl s_client -connect yourdomain.com:443 -showcerts

# Verify HAProxy config
haproxy -c -f /etc/haproxy/haproxy.cfg

# Enable detailed logging
option logasap
option httplog
log 127.0.0.1 local0 debug

Remember that HAProxy 1.5.8 is quite old (released 2014) and lacks many modern SSL features. Consider upgrading to at least 1.8 or 2.x for better SSL/TLS support.