0

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?

András Korn
  • 651
  • 5
  • 15
  • 1
    Be aware that HTTP/2 can cause problems here. See [this post](https://serverfault.com/a/1001319/227482). – turbophi Jan 31 '20 at 23:34

2 Answers2

4

I ended up using nginx with the stream SSL preread module.

The configuration is dead simple:

stream {
    server {
        resolver 127.0.0.1;
        listen 443;
        ssl_preread on;
        proxy_pass $ssl_preread_server_name:443;
    }
}

No http { } block would even be needed, but nginx segfaulted for me if I omitted it, so I have an empty http { } block in the config. Only the stream module is loaded. The resolver 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.

András Korn
  • 651
  • 5
  • 15
1

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

NickRamirez
  • 165
  • 1
  • 9
  • Thanks! Would you care to flesh this answer out a bit, maybe provide a working example configuration? – András Korn Jun 16 '19 at 20:33
  • 1
    My original thinking was to use 'ssl_fc_sni' to grab the SNI value, store it in a variable and then choose the backend. But actually you can use ssl_fc_sni directly in an ACL statement to choose a backend. But, I also see you want to do a DNS lookup and then transparently proxy the request. I'm not sure about the transparent proxy party, but HAProxy 2.0 introduced "do-resolve" which lets you do a DNS lookup dynamically: https://www.haproxy.com/blog/haproxy-2-0-and-beyond/#new-request-actions – NickRamirez Jun 17 '19 at 03:40