HAProxy SSL Farm Options

I am trying to figure out how to set up an SSL farm with haproxy and SSL reverse proxies and I am looking for some general advice:

Is it possible to meet all of the following:

  • Load balance requests against the SSL farm and have failover so more than one SSL box will be possible (perhaps the sslcheck in haproxy will help with this).
  • Get an HTTP log that has the actual client IP addresses in it.
  • No TProxy Requirement

If all 3 of these are not possible I am wondering what the tradeoffs might be. Right now I am considering something like the following but this could change:

Haproxy 443 TCP Proxy Frontend -> SSL Proxies (Maybe Nginx) on High Ports -> Haproxy HTTP Front-End -> Webservers

I realize I could probably skip the second hop back to haproxy but the single perspective of everything in HAproxy might be nice. Also if I have to use TProxy, maybe going back to haproxy from the SSL farm will make the routing simpler?

References:
http://haproxy.1wt.eu/download/1.5/doc/configuration.txt
http://1wt.eu/articles/2006_lb/index_05.html


Solution 1:

Kyle,

if you only need fail-over for the SSL part and not load balancing, here's what I suggest. You install haproxy + keepalived + stunnel (patched) on two nodes. Keepalived owns the service address and checks for the presence of the stunnel and haproxy processes to compute its weight so that the node in best shape is the master. Stunnel receives the traffic on port 443 and locally forwards it to haproxy on any port you like. In order for haproxy to log the client's IP address, you need the x-forwarded-for patch for stunnel (you can find it on my site). You'll then tell haproxy to log the x-forwarded-for header.

There is a limitation however. If you support HTTP keep-alive, then stunnel will only add the x-forwarded-for header once, which is a bit problematic. At Exceliance, we've started working on a patch to forward the connection parameters from stunnel to haproxy instead of playing with the x-forwarded-for. That way, haproxy believes it gets its connection from the real client. If you're interested, tell me, we can send it to you once it's complete.

Solution 2:

OK, I'm seeing this rather late, but how about:

      VLAN1         VLAN2

INET -- | -- [SSL] -- | -- [HTTP Load Balancer]
        |             |
        | -- [SSL] -- | -- [WEB01]
        |             |
        | -- [SSL] -- | -- [WEB02]
                      |
                      | -- [WEB03] etc

In words:

  • Simple DNS Round Robin to publish x IP addresses for the service,
  • With front-end SSL proxies (Apache, nginx) responding directly on those IPs. (Optional but recommended, with something like VRRP, CARP or Linux-HA to to ensure high availability for these IPs.)
  • All SSL proxies send their requests to a one-armed load balancer (for ease of configuration, single point of LB/session management),
  • And lastly the LB sends the request to the web application servers.

A couple of things jump out:

  • HAProxy and the SSL proxies (nginx) are quite close in terms of features and use model in this architecture. Are other requirements to the plain HTTP load balancing (was rate limiting mentioned elsewhere)? If not, then it might be cleaner to skip HAProxy and only use one type of webserver for all SSL & LB handling (f.x. nginx).
  • DNS round robin is likely "good enough" for just coarsely spreading load out over 2-3 SSL proxies. But if you don't like it, then you can use L4 mechanisms.

Get an HTTP log that has the actual client IP addresses in it.

Assuming that the first HTTP level device adds the X-FORWARDED-FOR header, and you use something like something like this or F5's IIS plugins, this should work.