HAProxy is not working with SNI and ACLs

I am trying to get haproxy on a DR site to use acls with SNI and it ain’t cooperating. It presents the correct cert so SNI must be working but I cannot get it to select a backend based on the hostname in SNI.

When I check the configuration, I get the following

$ haproxy -c -V -f /etc/haproxy/haproxy.cfg

[WARNING]  (21486) : Proxy 'fe-dr-totalflood.com': L6 sample fetches ignored on HTTP proxies (declared at ./haproxy.cfg.tmp:176).
[WARNING]  (21486) : Proxy 'fe-dr-totalflood.com': L6 sample fetches ignored on HTTP proxies (declared at ./haproxy.cfg.tmp:177).
Warnings were found.
Configuration file is valid

I have no idea what the warning messages mean and I’ve put a note next to the corresponding lines in the following snippet.

frontend  fe-dr-totalflood.com
  mode      http
  bind      172.22.8.229:80
  bind      172.22.8.229:443 ssl crt dr-www.totalflood.com.crt crt dr-xml.totalflood.com.crt

  ## http->https redirect
  http-request redirect scheme https unless { ssl_fc }

  ## access control lists
  acl https ssl_fc
  acl letsencrypt-acl path_beg /.well-known/acme-challenge/
  acl www-acl req_ssl_sni dr-www.totalflood.com
  acl xml-acl req_ssl_sni dr-xml.totalflood.com

  # if Let's Encrypt, skip remainder and jump to the backend
  use_backend be-letsencrypt if letsencrypt-acl

  use_backend be-dr-www.totalflood.com if www-acl <------ 176
  use_backend be-dr-xml.totalflood.com if xml-acl <------ 177

  default_backend be-no-such-site

#------------------------------------------------
backend   be-dr-www.totalflood.com
  mode      http
  balance   roundrobin
  cookie    SERVERID insert indirect nocache maxidle 30m

  ## set the host name in the header
  acl h_host_exists req.hdr(Host) -m found
  http-request del-header Host if h_host_exists
  http-request set-header Host www.totalflood.com

  default-server check maxconn 100

  server  scadmzp2wb01 scadmzp2wb01.lereta.net:80 cookie scadmzp2wb01

#------------------------------------------------
backend   be-dr-xml.totalflood.com
  mode      http
  balance   roundrobin
  cookie    SERVERID insert indirect nocache maxidle 30m

  ## set the host name in the header
  acl h_host_exists req.hdr(Host) -m found
  http-request del-header Host if h_host_exists
  http-request set-header Host xml.totalflood.com

  default-server check maxconn 100

  server  scadmzxml01 scadmzxml01.lereta.net:80 cookie scadmzxml01

#------------------------------------------------
backend be-letsencrypt
  server localhost 127.0.0.1:8888

#------------------------------------------------
backend be-no-such-site
  server localhost 127.0.0.1:8888

When I try to access either site (dr-www.totalflood.com or dr-xml.totalflood.com) I always hit the default backend no matter what. I’ve tested this by changing the default backend to go other places. If I
append to either url the /.well-known/acme-challenge path, haproxy seems to send me to the correct place so Let’s Encrypt works.

What I cannot figure out is why the acls based on SNI information don’t work.

I am using version 2.4.2 of haproxy running on OracleLinux 8.

$ haproxy -v
HAProxy version 2.4.2-553dee3 2021/07/07 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2026.
Known bugs: http://www.haproxy.org/bugs/bugs-2.4.2.html
Running on: Linux 5.4.17-2136.304.4.1.el8uek.x86_64 #2 SMP Tue Feb 8 11:54:24 PST 2022 x86_64

Don’t use SNI. Use the host header.

  acl www-acl hdr_dom(host) dr-www.totalflood.com
  acl xml-acl hdr_dom(host) dr-xml.totalflood.com

If you want to use SNI (you don’t), then the docuementation clarifies how:

req_ssl_sni: Returns a string containing the value of the Server Name TLS extension sent by a client in a TLS stream passing through the request buffer if the buffer contains data that parse as a complete SSL (v3 or superior) client hello message. Note that this only applies to raw contents found in the request buffer and not to contents deciphered via an SSL data layer, so this will not work with “bind” lines having the “ssl” option.

So in your configuration (terminating SSL), you’d need to access SNI with ssl_fc_sni and not with req_ssl_sni.

HOWEVER using SNI here is completely useless and will lead to other issues. Stop using SNI and use the Host header instead. The host header should always be used whenever possible.

That worked. Thank you