HAProxy community

SSL termination does not work correctly (v2.0.8)

Hello,
I have a problem โ€“ I want to terminate SSL at haproxy and load balance a bunch of servers based on JSESSIONID and SNI. It is almost working, but fails exactly at what I need to do.
My config is this:
---------------CONFIG-------------
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy

daemon

    debug
    tune.ssl.default-dh-param 2048
    # Default SSL material locations
    ca-base /etc/ssl/certs
    crt-base /etc/ssl/private

    # See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
    ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE$
    ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
    ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets

defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 120m
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http

Bind front-end address and add SNI logic to separate regions

frontend www-unsecured
mode http
bind *:80
http-request redirect scheme https

    use_backend http-hq-servers if { hdr(host) -i jde-hq-h.domain.com }
    use_backend http-ru-servers if { hdr(host) -i jde-ru-h.domain.com }

frontend www-secured
bind *:443 ssl crt /etc/ssl/certs/ekg/wild.domain.com.pem
mode http
option httplog
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
log /dev/log local2 debug

use_backend http-hq-servers if { ssl_fc_sni -i jde-hq-h.domain.com }
use_backend http-ru-servers if { ssl_fc_sni -i jde-ru-h.domain.com }

backend http-hq-servers
mode http
balance leastconn
log /dev/log local2 debug
option forwardfor

    stick-table type string len 74 size 200k expire 120m
    stick store-response res.cook(JSESSIONID)
    stick match req.cook(JSESSIONID)


    server web-hq-1-port-11501.domain.com    10.11.2.11:11501  check maxconn 50
    server web-hq-1-port-11601.domain.com    10.11.2.11:11601  check maxconn 50

----------CONFIG------
Now what happens is that httpโ€“>https redirect works fine, and I get a nice front page of web server.
Stickiness within SNI group also works โ€“ I can see that JSESSIONID is in the sticky table.
But when I log into webserver, the next request back from web server goes to http (80) port.
as can be seen in log:

Nov 6 13:51:56 jde-load-html haproxy[4911]: 10.11.99.111:51334 [06/Nov/2019:13:51:56.735] www-secured~ http-hq-servers/web-hq-1-port-11501.domain.com 0/0/10 1997 โ€“ 7/6/0/0/0 0/0
Nov 6 13:52:12 jde-load-html haproxy[4911]: 10.11.99.111:51333 [06/Nov/2019:13:52:12.443] www-unsecured www-unsecured/ 0/-1/-1/-1/0 301 137 - - LR-- 8/2/0/0/0 0/0 โ€œPOST /jde/E1Menu.maf HTTP/1.1โ€
Nov 6 13:52:12 jde-load-html haproxy[4911]: 10.11.99.111:51337 [06/Nov/2019:13:51:56.745] www-secured~ http-hq-servers/web-hq-1-port-11501.domain.com 0/0/15722 7899 โ€“ 7/6/5/0/0 0/0

and I get redirected back to the first page.
When I disable this line [http-request redirect scheme https] (redirect to https at http port) in the www-unsecured frontend, then SNI switching works, sticky table works with http. From https I correctly get the front page, then I get bounced back to http, but instead of loop it works and stays in http.

How can I correctly terminate ssl and get this to work? The documentation also does not help, all the examples are similar, but just does not work for me. What am I doing wrong? :frowning:

Your backend application has links and forms pointing to http/port 80, which is exactly what your browser does.

You need to configure your application so that it uses HTTPS schemes internally, or no scheme at all.

Otherwise your application will keep forcing the browser to the unsecure frontend, which cannot work, because it redirects to the secure frontend (ignoring for example those POST requests).

Oh, ok, so itโ€™s the app, not my config.
Big thanks for confirming that :slight_smile: