At a first read I thought this was just a basic use-case for HAProxy: have two servers (Exchange and website in your case) and route requests to them based on the
Host header, and provide TLS termination.
However something seems off:
exchange server we need to do SSL passthrough
Is this an actual “requirement”? (Are you using TLS-based client authentication?)
(A) Because I read this “SSL passthrough” as: HAProxy should receives the TCP connection, inspects the SNI host from the TLS handshake, and if it is for the Exchange server just pass TLS data back-and-forth without “touching” (i.e. terminating and re-encrypting) the traffic.
(B) Or, is it acceptable for HAProxy to terminate the TLS connection (i.e. decipher the TLS connection), and if it is for Exchange, create another separate TLS connection to the server and pass the original request. (In this variant HAProxy would act as a “man-in-the-middle” by having access to the un-encrypted data between the client and Exchange, however still having encrypted data on the network; meanwhile in the first case, it wouldn’t.)
Assuming it’s (B), that’s trivial.
Assuming it’s (A), I think it is possible with HAProxy, although never done it myself. My assumption is that you need to:
- create a
mode tcp frontend, which does not use
ssl in the
- then by leveraging
req.ssl_sni (http://cbonte.github.io/haproxy-dconv/1.8/configuration.html#7.3.5-req.ssl_sni), you could identify within the TLS data traffic any connections that have the hostname of the Exchange server, and use that to choose the Exchange dedicated backend;
- however if this is not the case (use
default_backend to) send the request to a
backend which has a
server listening on loopback (perhaps using the
send-proxy-v2 option), and
- create another
mode http that binds with
ssl on that local loopback address, thus terminating the TLS connection;
- within this second backend you can now use
Host header based routing like in a normal use-case;
- (additionally you could have this second frontend listen also on
http and redirect requests on
I would strongly suggest sticking with the more simple (B) variant, unless you have a really good reason not to do so.