RousselTMLEARNING

Article · HAProxy: from discovery to expertise

SSL Termination and Offloading

1. SSL termination (offloading) #

HAProxy handles decryption to relieve the web servers.

Configuring the certificate #

This is the most common method. HAProxy holds the SSL certificate and communicates in plain HTTP with the backends on a secure private network.

frontend https-in
    bind *:443 ssl crt /etc/ssl/certs/mon-site.pem
    default_backend app_servers

Note: the .pem file must contain the certificate and the private key.

2. SSL passthrough #

Forwarding the encrypted stream without inspection.

Using TCP mode #

If you don't want HAProxy to decrypt traffic (for complete confidentiality), use TCP mode (layer 4).

frontend stream-in
    mode tcp
    bind *:443
    default_backend secure_web

3. Forcing HTTPS #

Automatically redirecting users to the secure port.

HTTP to HTTPS redirection #

A simple rule in the HTTP frontend is enough.

frontend http-in
    bind *:80
    http-request redirect scheme https unless { ssl_fc }

Conclusion #

A central point for security.

Performance and security #

By centralizing SSL, you simplify certificate management (e.g. Let's Encrypt) and optimize the performance of your application servers.

Hands-on: certificates and full configuration #

Generate a certificate, configure and test.

Preparing the certificate #

HAProxy expects a single PEM file containing the certificate chain followed by the private key.

# Certificat auto-signé pour tester
openssl req -x509 -newkey rsa:4096 -nodes -days 365 -keyout app.key -out app.crt -subj "/CN=app.exemple.fr"
cat app.crt app.key > /etc/haproxy/certs/app.pem && chmod 600 /etc/haproxy/certs/app.pem

# Vérifier le contenu et la date d'expiration
openssl x509 -in /etc/haproxy/certs/app.pem -noout -subject -enddate

HTTPS frontend and redirection #

SSL termination with HAProxy
HAProxy relieves the servers of the cost of encryption.
global
    ssl-default-bind-ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

frontend https_in
    bind *:80
    bind *:443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1     # un répertoire = plusieurs certificats (SNI)
    http-request redirect scheme https unless { ssl_fc }
    http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains"
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
    default_backend app

backend app
    balance roundrobin
    server web1 10.0.0.11:8080 check
    server web2 10.0.0.12:8080 check

Testing and troubleshooting #

haproxy -c -f /etc/haproxy/haproxy.cfg && sudo systemctl reload haproxy
curl -vkI https://app.exemple.fr 2>&1 | grep -E "SSL|TLS|HTTP/"
openssl s_client -connect app.exemple.fr:443 -servername app.exemple.fr </dev/null 2>/dev/null | openssl x509 -noout -dates -issuer
nmap --script ssl-enum-ciphers -p 443 app.exemple.fr          # lister les suites acceptées
echo "show ssl cert" | sudo socat stdio /var/run/haproxy.sock    # certificats chargés (Runtime API)
Good practice: Automate renewal with ACME (see the ACME article) and reload HAProxy without interruption with systemctl reload haproxy or the Runtime command set ssl cert.

SSL passthrough #

Leaving encryption to the backends.

Configuration #

With SSL passthrough, HAProxy does not decrypt: it works in TCP mode and routes based on the name requested in the TLS message (SNI). The backends keep their certificates; HAProxy sees neither URLs nor headers.

frontend tls_in
    bind :443
    mode tcp
    tcp-request inspect-delay 5s
    tcp-request content accept if { req.ssl_hello_type 1 }
    use_backend app_tls if { req.ssl_sni -i app.example.com }
    default_backend web_tls

backend app_tls
    mode tcp
    server app1 10.0.0.11:443 check
ModeHAProxy sees HTTPCertificate on HAProxyUse
TerminationYesYesRouting by URL, headers, WAF
Re-encryptionYesYes (and on the backends)End-to-end encryption requirement
PassthroughNoNoCertificates managed by the application, end-to-end mTLS

📄 HAProxy and SSL: TLS termination, SSL passthrough and hardening →

My progress

  • ⏱ Estimated time : ≈ 10 min

Sign in to track your progress and take notes. Sign in

💬 Questions about this lesson

No questions yet: be the first to ask for help or share your configuration.

Ask a question about this lesson →

Recommended Articles

Anatomy of HAProxy configuration, clustering and high availability

Understand the structure of an haproxy.cfg file: the global, defaults, frontend (high performance...

Advanced Elasticsearch security: TLS, certificates, API keys, FLS, DLS and audit

Secure Elasticsearch in depth: transport and HTTP TLS, certificate management with elasticsearch-...

Load balancing: principles, algorithms and use cases

Discover how load balancing works, its role in high availability, and the details of algorithms s...

Visualizing your infrastructure with HAProxy Topology Visualizer

Learn how to use HAProxy Topology Visualizer to turn complex haproxy.cfg files into interactive d...

HAProxy: adding and removing backends dynamically

Learn how to use the HAProxy Runtime API to create, configure and delete backends and servers on ...

The HAProxy ecosystem: Open Source, Enterprise, HAProxy Fusion, Edge and HAProxy One

Understand the differences, advantages and connections between HAProxy OSS, Enterprise, Fusion, E...

Traefik best practices: security, high availability and observability

Traefik best practices: securing the dashboard and the Docker socket, modern TLS, middlewares, ra...

Health checks and high availability

How HAProxy detects failures and handles automatic failover to healthy servers.

Session persistence (stickiness)

Understanding how to ensure a user stays on the same backend server for the whole session.

Support us

♥ SUPPORT US

Support RousselTM Learning

Courses, articles, labs and certificates stay free with no intrusive ads. A voluntary contribution, of any amount you choose, pays for hosting, lab environments and new content.

Contribute with PayPal Any amount · card or PayPal accountLearn more
QR code PayPal
Or scan this QR code with your phone

Thank you, every contribution counts!