Drupal behind HAProxy and Stunnel for SSL

We encourage users to post events happening in the community to the community events group on https://www.drupal.org.
wxman's picture

Hello

I'm going to be running a two-node load balancer in an active/passive configuration with HAProxy and Heartbeat. This will be in front of at least two Apache backend servers. I have several Drupal sites, and a few of them need SSL, so it looked to me as if Stunnel with HAProxy would be the best option in the load balancers. I have separate public IP addresses for each of the SSL certs, and I'm on my own network, so I have all the internal IP's I need. After doing some reading around here, I find myself confused on how Drupal handles traffic from the load balancer. Some of what I was reading made it seem that Drupal can't tell from this kind of set up whether or not the traffic is SSL or not. Is this true, or am I making this more complicated than I need?

Comments

If the SSL end-point is on

lostchord's picture

If the SSL end-point is on the load balancer then the web servers will only see normal unencrypted traffic. You probably have to have a header inserted to signal that SSL was used. If you want to make sure that some pages are only being accessed via SSL whilst others are in the clear then you would probably want to do redirects if the protected pages are accessed over an unprotected channel.

I'm looking at this sort of configuration as well and the database side of it looks the tricky bit unless you have a seperate Db server that all the web servers access. Have you cracked that problem?

cheers

nginx

gchaix's picture

I'm accepting and routing SSL content to multiple backend servers using nginx. My flow basically looks like:

SSL->nginx (on our cache/load balance server)->SSL->Apache/PHP backends

It works seamlessly and the traffic is encrypted all the way through to the Apache nodes.

The config in nginx is simple. In nginx.conf I set up a couple of "upstream" servers and include a vhosts directory to tell nginx what traffic needs to go to which backend:

    upstream backend1_secure {
        server 10.2.1.40:443;
    }

    upstream backend2_secure {
        server 10.2.1.33:443;
    }

    include /etc/nginx/vhosts/*.conf;

vhost.conf:

server {
    listen        10.2.1.134:443;
    server_name    *.domain.org domain.org;

    ssl on;
    ssl_certificate        /etc/nginx/ssl/_.domain.org.crt;
    ssl_certificate_key    /etc/nginx/ssl/domain.key;

    access_log      /var/log/nginx/domain.ssl_access_log combined;
    error_log       /var/log/nginx/domain.ssl_error_log warn;

    location / {
        proxy_pass    https://backend1_secure;
    }
}

I'm spreading out my traffic to separate backends by domain using multiple "upstream" sections, but you could easily set up multiple "server" entries in the upstream sections of the nginx.conf instead and have it do a round robin load balance among the multiple backends - see http://wiki.nginx.org/NginxHttpUpstreamModule for syntax.

Interesting

lostchord's picture

Can you clarify a couple of things?

(1) You have a public certificate on the load balancer that the client sees when it establishes the session and additional certificates on each backend server?
(2) The load balancer encrypts/decrypts all traffic to the client and also encrypts/decrypts all traffic between itself and the backend servers?

How big a hit is the encrypt/decrypt compute load and what sort of upper limit does that place on your throughput?

cheers

Clarifications

gchaix's picture

For non-SSL traffic we're running Varnish on the front end. So it's not really a load balancer but more a cache server. Since Varnish doesn't handle SSL and we didn't want the traffic to be cached unencrypted, we chose to put nginx in place on 443 while Varnish handled 80. They essentially do the same thing routing the traffic to the appropriate backend Apache node, except that nginx handles SSL while Varnish caches.

1) Yes. We have a public cert on the cache server that the clients see when they connect. Our certs are not locked to a specific IP, so the backend servers actually have the same valid SSL cert as the frontend, they're just not visible or used by the clients. I haven't tried a self-signed cert on the backends to see if a valid cert is required for the nginx frontend <-> Apache backend communication.
2) Yes, nginx is encrypting and decrypting both sides of the conversation. Nginx is acting as a transparent proxy that just happens to talk only on SSL to both the clients and the backends.

I haven't noticed much in the way of load, but we only use SSL for login/logout and some admin stuff. We don run much traffic at all through the SSL ports.

-Greg

I was going to ask the same

wxman's picture

I was going to ask the same thing.
Also, are you using nginx as the load balancer, as well as the front end for the SSL?

I had actually read that

wxman's picture

I had actually read that already. It was interesting. I swear I've looked at all the articles on the web about this.

No, we're using Varnish for

gchaix's picture

No, we're using Varnish for the non-SSL traffic handling. Varnish caches whatever it can and then chooses the proper backend to pull content that's not in cache.

I don't mean to sound so

wxman's picture

I don't mean to sound so confused about this, but I've actually never thought of load balancing by domain instead of load. Am I correct that you do it that way; by hosting the sites on different backend servers, then routing the traffic to which ever server it needs to go to? If that is the case, then you don't even need anything like HAProxy?

I always thought that I needed two or more servers with identical content, and then the load balancers split the traffic as the load increased. Your way actually sounds easier, because you don't have to worry about keeping the backend servers identical.

I'm not using HAProxy at all.

gchaix's picture

I'm not using HAProxy at all. I have two essentially identical boxes with the same Varnish config on them. I don't do any sort of automated failover right now (mostly because I've been too lazy to set it up), but it'd be easy enough to set up a heartbeat between the two and have the backup come up on the primary's IP if it fails.

The Varnish config looks at the domain in the request and routes to the appropriate backend. It serves my particular needs well - many small sites each on a unique domain name. I don't have to worry about syncing the webroots/files that way. I intend to, though, in the near future switch to a shared filesystem for the webroots and have Varnish track which backends are up so I can take backend nodes offline for maintenance without taking sites down.

HAProxy allows you to make

lostchord's picture

HAProxy allows you to make routing decisions based on application layer (layer 7) data. So you can direct traffic to hosts based on almost anything, load balancing can then be put into the mix.

I'm experimenting with mixing HAProxy for plain HTTP traffic with Pound for HTTPS. They look like they should play nicely since they support similar layer 7 routing rules and session stickiness can be harmonised using cookies.

All theory at present though :-)

chhers

That sounds like what I'm

wxman's picture

That sounds like what I'm trying now, except that I'm trying Nginx for the SSL.

First of all thanks for the

wxman's picture

First of all thanks for the advice. I'm working on setting up a test server just for this. I wish there was a way to really test it all the way through to a Drupal SSL/non SSL site, but I haven't figured that out yet.

There is an excellent how-to at http://www.cyberciti.biz/faq/howto-linux-unix-setup-nginx-ssl-proxy/ on setting up nginx for this.

I was wondering if anyone has had any luck setting up Drupal sites in this configuration, but using multiple SSL certificates? I see how to set up Nginx for multi SSL's, and it looks like every time a new SSL site is added to the apache backend, you will need to add separate upstream{} and server{} sections for each of them.

If I get this working, I'm also going to see if I can incorporate static file caching into the Nginx setup. I would think that would boost the performance on a slow backend server.,

I forgot to ask about

wxman's picture

I forgot to ask about fail-over situations? The way I was setting up, I had two identical load balancer on separate machines. They were set using a shared floating internal IP address that switched to the backup load balancer if the first went out. If I set it up this new way, won't I have to have separate IP's for Nginx and Varnish? I guess I could still float two common IP's between the two load balancers.

Varnish and nginx are on the

gchaix's picture

Varnish and nginx are on the same IP. Varnish listens on :80 while nginx listens on :443. No need for multiple IPs.

As for failover, it depends on your needs. My particular situation doesn't require instant failover, so I just have a second box on standby configured and ready to go. If the primary fails, I just bring up the primary's IP as a secondary interface on the backup box and we're back in business. It should be easy enough to do it automatically with heartbeat or the floating IP technique you're referring to.

Subscribe

anonymous07's picture

Incredibly useful and informative topic and thread. Been trying to get name-based multisite ssl going (i.e., TLS, mod_gnutls, etc) and ... well .... it ain't easy. LOL I am watching to see if stunnel might be a viable alternative and what the pros/cons of either method are.