How do I force-change the backend's cert?

I’ve long struggled getting HAProxy to offload the certificate of a server; ADFS. HAProxy makes an encrypted connection of its own to ADFS, then it’s supposed to switch the certificate with something matching from the specified ones but what it actually happens is that the original(…origin?) certificate makes it through all the way to the client.

Because of the server in question, I assume some sort of heightened security (end-to-end or something) is specified in it which HAProxy obeys thus it doesn’t change the cert. I discovered I could work around this by adding NAT in front of ADFS or mapping ADFS to a virtual IP address —i.e; fancier NAT— so when things were working again I moved on.

While testing one of these apps that will only will let you do certificates from HTTP-01 ACME Let’sEncrypt. No problem, I thought, I’ll just disguise it with HAProxy; it’s already in front of every server even on the intranet. When I did though, Firefox showed me the unknown CA warning. On the details of the cert I saw that it was the same certificate from the server. The backend server I believe is using NGINX as a reverse proxy.

It’s setup to terminate the connection (TLS offloading). It passes through the SNI frontend first, but all TLS connections do;

Is there something I could do to force HAProxy to terminate the connection so the certificate is switched?

Thanks!


I added the actual configuration of only the related frontends and backends. I also removed the irrelevant keywords from it because it still was way too long.

Configuration file sections
frontend port443raw
  bind      0.0.0.0:443 name 0.0.0.0:443   
  (…)
  bind      ::1:443 name ::1:443   
  mode      tcp
  (…)
  timeout client    30000
  errorfile      400 /var/etc/haproxy/errorfile_port443raw_400_sc400.http
  (…)
  errorfile      504 /var/etc/haproxy/errorfile_port443raw_504_sc504.http
  tcp-request inspect-delay  5s
  acl      skypeav  req.ssl_sni -m sub -i skype
  tcp-request content accept if { req.ssl_hello_type 1 }
  use_backend skypeav-sni443  if  skypeav 
  default_backend loopback-main

  frontend port443
  bind      …   ssl crt-list /var/etc/haproxy/port443.crt_list  
  (…)
  bind      –   ssl crt-list /var/etc/haproxy/port443.crt_list  
  bind      /tmp/haproxy_chroot/port443.socket name unixsocket accept-proxy   ssl crt-list /var/etc/haproxy/port443.crt_list 
  mode      http
  option    http-keep-alive
  option    forwardfor
  acl https ssl_fc
  http-request set-header    X-Forwarded-Proto http if !https
  http-request set-header    X-Forwarded-Proto https if https
  errorfile      400 /var/etc/haproxy/errorfile_port443_400_sc400.http
  (…)
  errorfile      504 /var/etc/haproxy/errorfile_port443_504_sc504.http
  acl      w3  var(txn.txnpath) -m dir -i statcap
  acl      mwkc  var(txn.txnpath) -m sub -i /.well-known/matrix/client
  acl      mwks  var(txn.txnpath) -m sub -i /.well-known/matrix/server
  acl      matrixpath  var(txn.txnpath) -m beg -i /_matrix
  acl      matrixpath  var(txn.txnpath) -m beg -i /_synapse/client
  acl      matrixhost  var(txn.txnhost) -m beg -i matrix.
  acl      routelogic  var(txn.txnhost) -m beg -i routelogic.
  acl      ref  var(txn.txnhost) -m beg -i ref.
  (…)
  acl      y  var(txn.txnpath) -m str -i y.d.one
  acl      y  var(txn.txnpath) -m beg -i titsup.
  acl      aclcrt_port443  var(txn.txnhost) -m reg -i ^domainTWO\.com(:([0-9]){1,5})?$
  acl      aclcrt_port443  var(txn.txnhost) -m reg -i ^([^\.]*)\.domainTWO\.com(:([0-9]){1,5})?$
  acl      aclcrt_port443  var(txn.txnhost) -m reg -i ^([^\.]*)\.domainTHREE\.com(:([0-9]){1,5})?$
  acl      aclcrt_port443  var(txn.txnhost) -m reg -i ^([^\.]*)\.domainONE\.link(:([0-9]){1,5})?$
  acl      aclcrt_port443  var(txn.txnhost) -m reg -i ^domainTHREE\.com(:([0-9]){1,5})?$
  http-request set-var(txn.txnpath) path
  http-request set-var(txn.txnhost) hdr(host)
  http-after-response set-header server "domainONE FrontMaster"  if   aclcrt_port443
  http-after-response set-header X-XSS-Protection "1; mode=block"  if   aclcrt_port443
  http-after-response set-header X-Content-Type-Options nosniff  if   aclcrt_port443
  http-after-response set-header Cache-Control "stale-while-revalidate=86400"  if   aclcrt_port443
  http-after-response set-header X-Robots-Tag noindex  if  !w3 !testtls !fnck aclcrt_port443
  http-after-response set-header Feature-Policy "sync-xhr 'none'"  if  !fnck !domotica !oos !docs aclcrt_port443
  http-after-response set-header Content-Security-Policy "object-src …"  if  !oos !fnck !docs aclcrt_port443
   http-after-response add-header Content-Security-Policy "img-src *;"  if  ref oos docs fnck aclcrt_port443
   http-after-response add-header Content-Security-Policy "img-src 'self' …;"  if  !domotica !fnck !docs aclcrt_port443
   http-after-response add-header Content-Security-Policy "img-src 'self' …;"  if  !ref !domotica !fnck aclcrt_port443
   http-after-response add-header Content-Security-Policy "script-src 'self' …;"  if  !ref !oos !fnck !portainer aclcrt_port443
   http-after-response add-header Content-Security-Policy "script-src 'self' …t;"  if  ref !oos aclcrt_port443
   http-after-response add-header Content-Security-Policy "style-src 'self' '…;"  if  !ref  !fnck aclcrt_port443
   http-after-response add-header Content-Security-Policy "style-src 'self' '…t;"  if  ref aclcrt_port443
   http-after-response add-header Content-Security-Policy "frame-ancestors htt;"  if   !fnck aclcrt_port443
   http-after-response add-header Strict-Transport-Security "max-age=15778476"  if  !domotica !oos !routelogic !cloudfront aclcrt_port443
  http-request redirect location https://unificontroller.d.one:8443/ code 303  if  unifi aclcrt_port443
  http-request redirect location http://%[req.hdr(host),lower,regsub(www\.,,i)] code 303  if  www aclcrt_port443
  http-after-response del-header link  if   aclcrt_port443
  http-after-response add-header Content-Security-Policy "script-src 'self' …;"  if  fokmihard aclcrt_port443
  use_backend w3-sec443  if  ref aclcrt_port443
  use_backend w3-sec443  if  w3 aclcrt_port443
  (…)
  use_backend y-sec443  if  y aclcrt_port443
  use_backend redir404  if   aclcrt_port443

backend loopback-main
  mode      tcp
  load-server-state-from-file  global
  server      frontend-main /port443.socket send-proxy-v2-ssl-cn check inter 12000  resolvers domaincontrollers 

backend y-sec443
  mode      http
  http-check    send meth OPTIONS ver HTTP/1.1\r\n\Host:\ */*
  load-server-state-from-file  global
  option      httpchk
  http-request disable-l7-retry if METH_POST
  http-check expect !rstatus ^5
  acl statcapmatch var(txn.txnpath) -m dir -i statcap
  http-request replace-path (\/statcap\/)(.*)$ \1\2 if statcapmatch
  http-request set-header Host status.d.one if statcapmatch
  server      v4 10.5.0.43:443 ssl check inter 12000  verify none resolvers domaincontrollers observe layer7 error-limit 10 on-error fastinter inter 12s 

That’s properly indented in the config file:

frontend port443
  bind      …   ssl crt-list /var/etc/haproxy/port443.crt_list 

Oh well, I guess I’ll try my luck reverse-proxying with Apache’s httpd.

There should be an option to delete or close the thread. :confused:

When you configure the ssl keyword on a bind configuration statement, then haproxy will terminate the SSL connection with the specified certificate.

Absolutely not, haproxy will obey what you configure only and nothing else.

Use openssl (openssl (openssl s_client -connect 127.0.0.1:4443 -servername www.example.org) against backend directly, against haproxy port 443 (the non-SSL-terminating one in tcp mode) and put a port in the SSL terminating frontend to check that too.

Stop haproxy completely, make sure that no old haproxy instances are lurking in the background, kill them all if they are, and restart haproxy.

Share the full bind statements, and full haproxy logs. The names in your diagram do not match your configuration.