HAProxy is a load balancer and proxying for TCP and HTTP based applications. This software is supported for very common Unix and Linux based systems, and works with multiple protocols. HAProxy is very common used as a frontend http servers and has a flexible configuration to send the requests to the backends, it’s possible also to create access lists to send determinates requests to a pool of servers depending on the resource requested by the client.
In this post I’ll configure HAProxy as web server frontend and two backends running an application under a web server. On the connection between the clients and the frontend I’ll configure https, while the connection with the frontend and the backends will be as http. Here is when stunnel comes in, one way to provide from the frontend an ssl connection is with it. Stunnel only acts as intermediate between the client with an https request and the haproxy, redirecting this connection from the port 443 to haproxy frontend listening the port 80 configured in this scenario.
The final architecture would look like the image:
In this scenario I’ll explain the configuration of the frontend (haproxy+stunnel), I’ll obviate the configuration of the backends.
**NOTE: From 1.5.x branch version comes with SSL support natively with HAProxy, actually this version is still in development:
http://cbonte.github.com/haproxy-dconv/configuration-1.5.html#5-crt
Preparing the environment
– Download and install EPEL repository:
32 bits:
# rpm -ivh http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-7.noarch.rpm
64 bits:
# rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-7.noarch.rpm
– Installing haproxy and stunnel:
# yum -y install haproxy stunnel
– Creating self-signed certificate:
# openssl genrsa -out /etc/ssl/certs/private.key 2048 # openssl req -new -x509 -key /etc/ssl/certs/private.key -out /etc/ssl/certs/cert.pem -days 432
– Adding private key and certificate in a single file (necessary with stunnel):
# cat /etc/ssl/certs/private.key /etc/ssl/certs/cert.pem > /etc/stunnel/cert-key.pem
Configuring stunnel
– Edit config file:
# vi /etc/stunnel/stunnel.conf
sslVersion = SSLv3 chroot = /var/run/stunnel/ cert = /etc/stunnel/cert-key.pem key = /etc/ssl/certs/private.key setuid = nobody setgid = nobody pid = /stunnel.pid debug = 7 output = /var/log/stunnel.log [https] accept = 172.16.0.100:443 connect = 172.16.0.100:80
– Creating the chroot directory for stunnel:
# mkdir /var/run/stunnel # chown nobody:nobody /var/run/stunnel/
– Run stunnel:
# stunnel /etc/stunnel/stunnel.conf
Configuring HAProxy
– Edit haproxy configuration:
# vi /etc/haproxy/haproxy.cfg
#--------------------------------------------------------------------- # Global settings #--------------------------------------------------------------------- global log 127.0.0.1 local2 chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 user haproxy group haproxy daemon # turn on stats unix socket stats socket /var/lib/haproxy/stats #--------------------------------------------------------------------- # common defaults that all the 'listen' and 'backend' sections will # use if not designated in their block #--------------------------------------------------------------------- defaults mode http log global option httplog option dontlognull option http-server-close option forwardfor except 127.0.0.0/8 option redispatch retries 3 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn 3000 #--------------------------------------------------------------------- # main frontend which proxys to the backends #--------------------------------------------------------------------- frontend balancer_server bind 172.16.0.100:80 default_backend app_pool #--------------------------------------------------------------------- # round robin balancing between the various backends #--------------------------------------------------------------------- backend app_pool balance roundrobin cookie app_cookie insert indirect nocache server backend1 172.16.0.101:80 weight 1 cookie backend1 check inter 1000 server backend2 172.16.0.102:80 weight 1 cookie backend2 check inter 1000 option httpclose
This configuration will provide a cookie persistence based created by haproxy with the name app_cookie. The persistence is necessary to applications that stores information session of a client and only the backend server has this information session, so with the persistence we’ll ensure that the same backend will reply a request from the client. There are some methods for persistence, in this configuration the cookie created by haproxy will call app_cookie and the values to identify the backend will be backend1 or backend2. Another method to ensure the persistence may be based on the source ip address, it may be a solution if in the case for example that the https connection is directly with the backend instead the frontend, due that the connection will be encrypted and haproxy will not access to the http headers for check the cookie session.
HAProxy will check to the backends every seconds, if one backend fails haproxy will not send the request to this backend.
– Restart HAProxy service:
# /etc/init.d/haproxy restart
– Sources:
http://haproxy.1wt.eu/download/1.4/doc/configuration.txt
http://code.google.com/p/haproxy-docs/wiki/cookie