I'm in a situation where I have to provide a transparent reverse proxy in front of a set of thousands of backend https webservers, with the list changing (relatively) frequently.
I know I can tell haproxy
to select a backend to connect to based on the SNI string the client sends along with the Client Hello (see e.g. Can a Reverse Proxy use SNI with SSL pass through?), but it seems I would need to enumerate all backends and refer to them individually in the configuration; i.e. "if SNI is so-and-so, talk to backend this-and-that".
I'd instead like to just take the SNI string from the Client Hello, look it up in DNS, connect to the IP DNS provides (on tcp port 443), relay the client hello to the server, and then keep relaying between the client and the server.
I don't want to inspect the traffic and don't want to install a new certificate on the clients.
Can haproxy do this? If not, what other program can?
I ended up using
nginx
with the stream SSL preread module.The configuration is dead simple:
No
http { }
block would even be needed, butnginx
segfaulted for me if I omitted it, so I have an emptyhttp { }
block in the config. Only the stream module is loaded. Theresolver
is needed for nginx to be able to look up the backend names in DNS; I have a caching recursive resolver on 127.0.0.1.I make it so all clients that need to connect to any of the backends connect to my nginx instead (using a combination of split horizon DNS and DNAT), and nginx connects to the actual backends on their behalf. It's completely transparent to the clients.
You can set variables in HAProxy with http-request set-var to the SNI value and reference it with var.
https://www.haproxy.com/documentation/hapee/1-9r1/onepage/#7.3.2-var