HAProxy can terminate TLS and then re-encrypt traffic to your backends, or it can just pass the encrypted TLS traffic straight through to the backends without HAProxy ever seeing the plaintext. The latter is called SSL passthrough.

Here’s HAProxy in action, configured for SSL passthrough:

frontend http_frontend
    bind *:443 ssl crt /etc/ssl/certs/mycert.pem
    mode tcp
    default_backend tcp_backends

backend tcp_backends
    mode tcp
    server server1 192.168.1.10:443 check
    server server2 192.168.1.11:443 check

In this configuration, HAProxy listens on port 443 for incoming TLS connections. The mode tcp directive is crucial here; it tells HAProxy to operate at the transport layer, treating the traffic as raw TCP packets rather than HTTP. The ssl crt /etc/ssl/certs/mycert.pem part tells HAProxy to enable SSL/TLS on this frontend, but it doesn’t mean HAProxy will decrypt the traffic. It simply uses the certificate for SNI matching or other TLS-level metadata if needed, but the actual TLS handshake and encryption/decryption happen end-to-end between the client and the backend server.

The default_backend tcp_backends line directs all incoming traffic on this frontend to the tcp_backends pool.

The backend tcp_backends section defines the servers that will receive the traffic. Again, mode tcp is used. The server lines specify the IP addresses and ports of the backend servers. Importantly, these backend servers are also listening on port 443 and are expected to handle their own TLS termination. HAProxy simply forwards the encrypted TCP packets to these destinations. The check directive enables health checks, ensuring HAProxy only sends traffic to healthy backend servers.

This setup is particularly useful when you have backend applications that manage their own TLS certificates, or when you want to offload the processing of TLS encryption/decryption to the backend servers themselves. HAProxy acts as a simple TCP proxy, forwarding the encrypted traffic without inspecting or modifying it. This can reduce the load on HAProxy and simplify certificate management if your backend applications already handle it.

The primary benefit of SSL passthrough is that it allows the backend servers to have full control over the TLS session. This means they can use their own specific certificates, enforce their own cipher suites, and handle TLS renegotiation or other advanced TLS features without HAProxy interfering. It’s also a simpler configuration for HAProxy itself, as it doesn’t need to be aware of or manage backend TLS certificates.

The most surprising thing about SSL passthrough is that HAProxy doesn’t actually need a private key for the frontend if it’s only performing passthrough and not SNI-based routing or any other TLS inspection. The ssl crt directive in the frontend can point to a certificate bundle that HAProxy might use for SNI resolution, but if you’re not doing SNI and just blindly passing TCP, the certificate itself becomes less critical for HAProxy’s function. The client and server still perform a full TLS handshake, and HAProxy is just a conduit for that encrypted data.

When using SSL passthrough, HAProxy does not inspect the content of the TLS traffic. This means security features like Web Application Firewalls (WAFs) or deep packet inspection that typically require unencrypted traffic cannot be applied at the HAProxy layer. If you need these features, you would have to terminate TLS at HAProxy and then re-encrypt to the backends.

The next conceptual hurdle you’ll likely encounter is how to implement SNI routing with SSL passthrough if you have multiple backend services on different domains all terminating TLS on the same IP address.

Want structured learning?

Take the full Haproxy course →