My goal is to configure haproxy as loadbalancer for multiple web servers with tls. I found some articles and it states that ClientHello message can contain extension with server_name. IIUC this is unencrypted.

IIRC I saw some effort to "hide" such info because it can reveal what HTTPS data - from which FQDN - is a client requesting. OK, it is not revealing the data itself but "metadata" of connection, isn't it?

Thus does it make sense to configure haproxy is such way, ie. it checks value in server_name extention of ClientHello and forwards to valid HTTPS server? Or is it just better to have TLS ending directly on haproxy (ie. having keys/certs there) and forward with new TLS to backend servers?

(I'm little bit new in this area, so I apologize for my confusion.)

  • SNI is an extension for the client to specify which hosts it wants to connect to, and it is needed for HTTPS virtual hosting (multiple names on same IPs). There is work underway to have "encrypted SNI" as it is needed to thwart attempts to interception, as it is seen in the wild that various actors sniff the SNI and react on it. Also note that your question may be more on topic of Server Fault check its help. However "what is better" may yield to too many subjective replies. You should describe more in details your setup and constraints. – Patrick Mevzek Feb 19 '19 at 15:00
  • Yep, I was thinking about encrypted SNI, thank you. – Jiri B Feb 20 '19 at 0:55

Neither solution is different with regard to SNI. The client will send it, in the clear, whether HAProxy is merely "sniffing" the SNI and forwarding the connection to a backend based on its contents, or HAProxy is terminating TLS.

This is because, in TLS, the client "talks first" -- when the first device on the server side accepts the client's TCP connection (always HAProxy, regardless of configuration) the client initates the TLS handshake with its "client hello" message, including SNI.

If HAProxy is sniffing the SNI, it simply buffers what the client has sent, opens a second TCP connection to the backend (the first connection is to the browser), writed whatever the client has written, and then tying the payloads of the two streams together, tying up a connection to the server for as long as the client is connected, and placing the CPU burden of TLS on the backend server. In this configuration, HAProxy can't make any sophisticated routing decisions (such as by path patterns or cookies) because those pass through the proxy, encrypted.

If HAProxy is actually terminating TLS, then it has access to the unencrypted payload, can make routing decisions based on attributes of the request, and -- importantly -- can optimize the use of server resources by reusing server connections for different clients, and maintaining a typically much lower number of server connections than the number of connected clients, since clients will tend to sit on idle, open connections. HAProxy's event-driven model allows it to manage these idle connections at a much lower cost in resources than some web servers can. If you need the traffic from HAProxy to the backends to be encrypted in this configuration, HAProxy can optionally do that, too, by negotiating a separate TLS session with the back-end, independent of the TLS session with the client, and using different certificates. Unlike the external-facing certificates, these back-end certificates can be self-signed, since the client does not see them.

In short, while sniffing the SNI and passing through the TLS from client to back-end is possible, it removes your ability to use HAProxy's full potential, so is probably the path to choose only when you have a specific reason to choose it.

You are correct that SNI only exposes what might be called "metadata" -- not the actual encrypted payload -- the concern here is that the hostname of the web site the user is visiting is not information that is kept secret if the traffic is intercepted... but this is true regardless of which way HAProxy is configured, because SNI-capable clients send it autonomously in their initial interaction with the server -- the server doesn't advertise this capability.

  • Thank you, I had in mind encrypted SNI as described here cloudflare.com/ssl/encrypted-sni and blog.cloudflare.com/encrypted-sni I'll go what you recommended. – Jiri B Feb 20 '19 at 0:56
  • This is bleeding edge technology. I have not seen any discussion of this on the HAProxy mailing list, though it is possible that I may have overlooked it. If you were to use CloudFlare in front of HAProxy (a reasonable configuration) then the client's TLS would always be terminated by CloudFlare, with a separate TLS session established between CloudFlare and HAProxy, since CloudFlare is essentially a distributed proxy that behaves very much like HAProxy in the "TLS termination" scenario described a above -- plus a cache. So CloudFlare's protective measures would be what counts. – Michael - sqlbot Feb 20 '19 at 2:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.