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

Managing SSL/TLS certificates with Let's Encrypt and ACME

Learn how to automate the generation and renewal of your SSL/TLS certificates with Let's Encrypt....

The ACME protocol: ACME server, http-01 and dns-01 challenges, TLS automation

Understand the ACME protocol: the role of the ACME server (Let's Encrypt, ZeroSSL, step-ca), the ...

Mastering ACLs in HAProxy: the complete guide

A complete guide to HAProxy ACLs: learn how to configure smart routing, IP-based access control, ...

Mastering ACLs in HAProxy

A complete guide to HAProxy ACLs: learn how to configure smart routing, IP-based access control, ...

HAProxy as a Kubernetes Ingress Controller: the production guide

Learn how to use HAProxy as an Ingress Controller in Kubernetes: direct-to-pod architecture, TLS ...

HAProxy: a detailed guide to configuration directives

A complete exploration of HAProxy's essential directives: from bind to http-check, learn how to c...

HAProxy best practices: optimization, security and high availability

Discover the best practices for configuring HAProxy to ensure the performance, security and resil...

HAProxy in Kubernetes: the high-performance Ingress Controller

Discover in depth how HAProxy integrates with Kubernetes: direct-to-pod architecture, hot update ...

What's new in HAProxy: OpenTelemetry, native JWT and performance optimizations

Explore HAProxy's latest innovations: native OpenTelemetry support for observability, JWT validat...

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!