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:
haproxyStunnel

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

HTTPS Load Balancer with HAProxy & Stunnel
Tagged on:         

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Follow

Get every new post delivered to your Inbox

Join other followers: