HAProxy Load Balancer with Failover for Exchange 2013

vladimir simeonov
23/04/2014

1. setup ubuntu 12.04 LTS

2. update the setup to the latest package versions

    apt-get update    aptitude full-upgrade

3. install packages

aptitude install spread nfs-client libspread1 libspread1-dev libperl-dev dpatch flex bison autotools-dev cdbs

4. build haproxy

apt-get install haproxy

apt-get build-dep haproxy

sed -i -e “s/\/usr\/sbin\/haproxy/\/usr\/local\/sbin\/haproxy/” /etc/init.d/haproxy

dpkg -r haproxy

cd /usr/src

wget http://haproxy.1wt.eu/download/1.5/src/snapshot/haproxy-ss-LATEST.tar.gz

tar xzfv haproxy-ss-LATEST.tar.gz 

cd haproxy-ss-*/

make DESTDIR=debian/haproxy  \        PREFIX=/usr   \       IGNOREGIT=true    \      MANDIR=/usr/share/man    \      DOCDIR=/usr/share/doc/haproxy    \      USE_PCRE=1  \        USE_OPENSSL=1 \         TARGET=linux26       \             USE_LINUX_SPLICE=1      \              USE_LINUX_TPROXY=1 \
make install

sed -i -e “s/ENABLED=0/ENABLED=1/” /etc/default/haproxy

sed -i -e “s/ENABLED=0/ENABLED=1/” /etc/default/spread

5. build wackamole

cd /usr/src

wget http://ftp.de.debian.org/debian/pool/main/w/wackamole/wackamole_2.1.1.orig.tar.gz

wget http://ftp.de.debian.org/debian/pool/main/w/wackamole/wackamole_2.1.1-3.1.diff.g

ztar xzfv wackamole_2.1.1.orig.tar.gz

gunzip wackamole_2.1.1-3.1.diff.gz

cd wackamole-2.1.1/patch -p1 < ../wackamole_2.1.1-3.1.diff

cd /usr/src/

wget ftp://ftp.freebsd.org/pub/FreeBSD/ports/distfiles/wackamole-2.1.4.tar.gz

tar xzfv wackamole-2.1.4.tar.gz 

cd wackamole-2.1.4/

cp ../wackamole-2.1.1/config.sub .

./configure –with-cppflags=-I/usr/include         –with-ldflags=-L/usr/lib         –with-perl         –with-threads         –with-pid-dir=/var/run/wackamolemakemake install

cat <<EOF > /etc/init.d/wackamole

#!/bin/sh

### BEGIN INIT INFO

# Provides:          wackamole

# Required-Start:    $remote_fs $syslog

# Required-Stop:     $remote_fs $syslog

# Default-Start:     2 3 4 5

# Default-Stop:      0 1 6

### END INIT INFO


# Wackamole init script

# June 2003

# Eric Dorland

# Based on spamassassin init script

PATH=/sbin:/bin:/usr/sbin:/usr/bin

DAEMON=/usr/local/sbin/wackamole

NAME=wackamole

SNAME=wackamole

DESC=”Wackamole Virtual IP Daemon”

PIDFILE=”/var/run/$NAME/$NAME.pid”

PNAME=”wackamole”

DOPTIONS=”-c /etc/wackamole.conf”


# Defaults – don’t touch, edit /etc/default/wackamole

ENABLED=0

OPTIONS=””


test -x $DAEMON || exit 0


test -f /etc/default/wackamole && . /etc/default/wackamole

             

test “$ENABLED” != “0” || exit 0


case “$1” in

  start)

        echo -n “Starting $DESC: “

        start-stop-daemon –start –pidfile $PIDFILE \

                –name $PNAME –oknodo –startas $DAEMON \

            — $OPTIONS $DOPTIONS

        

        echo “$NAME.”

        ;;

  stop)

        echo -n “Stopping $DESC: “

        

        start-stop-daemon –stop –pidfile $PIDFILE –name $PNAME –oknodo

        

        echo “$NAME.”

        ;;

  restart|force-reload)

        echo -n “Restarting $DESC: “

        start-stop-daemon –stop –pidfile $PIDFILE –name $PNAME \

            –retry 5 –oknodo

        start-stop-daemon –start –pidfile $PIDFILE \

            –name $PNAME –oknodo –startas $DAEMON \

            — $OPTIONS $DOPTIONS

        

        echo “$NAME.”

        ;;

  *)

        N=/etc/init.d/$SNAME

        echo “Usage: $N {start|stop|restart|force-reload}” >&2

        exit 1

        ;;

esac


exit 0

cat <<EOF > /etc/default/wackamole

# Change to enable wackamole

ENABLED=1
# Options

OPTIONS=””

EOF

HAP-1/HAP-2:

/etc/haproxy/haproxy.cfg

defaults

  option  http-server-close  # set Connection: close to inspect all HTTP traffic

  option  dontlognull        # Do not log connections with no requests

  option  redispatch         # Try another server in case of connection failure

  option  contstats          # Enable continuous traffic statistics updates

  retries 3                  # Try to connect up to 3 times in case of failure 

  timeout connect 5s         # 5 seconds max to connect or to stay in queue

  timeout http-keep-alive 1s # 1 second max for the client to post next request

  timeout http-request 15s   # 15 seconds max for the client to send a request

  timeout queue 30s          # 30 seconds max queued on load balancer

  timeout tarpit 1m          # tarpit hold tim

  backlog 10000              # Size of SYN backlog queue

frontend ft_exchange_https

  bind 10.8.4.9:443 name https ssl crt /etc/haproxy/ssl/my.pem crt /etc/haproxy/ssl/my2.pem

  mode http

  log global

  option httplog

  capture request header User-Agent len 64

  capture request header Host len 32

  log-format %ci:%cp\ [%t]\ %ft\ %b/%s\ %Tq/%Tw/%Tc/%Tr/%Tt\ %ST\ %B\ %CC\ %CS\ %tsc\ %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ %hr\ %hs\ {%sslv/%sslc/%[ssl_fc_sni]/%[ssl_fc_session_id]}\ %{+Q}r

  timeout client 25s

  maxconn 1000

  no option httpclose

  no option forceclose

  no option http-server-close

  http-request redirect scheme   https code 302 if !{ ssl_fc }

  http-request redirect location /owa/ code 302 if { hdr(Host) mail.example.com } { path / }

  use_backend bk_exchange_https if { ssl_fc_sni mail.example.com } # content switching based on SNI

  use_backend bk_exchange_https if { ssl_fc_sni autodiscover.example.com } # content switching based on SNI

  default_backend bk_exchange_https

backend bk_exchange_https

  stick-table type ip size 10240k expire 60m

  stick on src

  balance roundrobin

  mode http

  log global

  option httplog

  option forwardfor

  cookie JSESSIONID prefix

  default-server inter 3s rise 2 fall 3

  timeout server 120s

  server iron 10.8.4.4:443 maxconn 1000 weight 10 ssl verify none check

listen stats :8080

    mode http

    stats enable

    stats hide-version

    stats realm Haproxy\ Statistics

    stats uri /

    stats auth user:pass

frontend ft_exchange_pop3s

    mode tcp

    bind 10.8.4.9:995 name pop3s ssl crt /etc/haproxy/ssl/mail_example_com.pem

    default_backend bk_exchange_pop3s

backend bk_exchange_pop3s

  mode tcp

  balance roundrobin

  stick store-request src

  stick-table type ip size 200k expire 30m

  timeout server 200s

  server iron 10.8.4.4:995 maxconn 1000 weight 10 ssl verify none check

  

frontend ft_exchange_imaps

    mode tcp

    bind 10.8.4.9:993 name pop3s ssl crt /etc/haproxy/ssl/mail_example_com.pem

    default_backend bk_exchange_imaps

backend bk_exchange_imaps

  mode tcp

  balance roundrobin

  stick store-request src

  stick-table type ip size 200k expire 30m

  timeout server 200s

  server iron 10.8.4.4:993 maxconn 1000 weight 10 ssl verify none check

/etc/wackamole.conf:

Spread = 4803

SpreadRetryInterval = 5s

Group = wack1

Control = /var/run/wackamole/wackamole.it

Prefer None

VirtualInterfaces {

        eth0:10.8.4.9/24

}

Arp-Cache = 60s

Notify {

        eth0:10.8.4.1/32

        eth0:10.8.4.0/24

        arp-cache

}

balance {

        AcquisitionsPerRound = all

        interval = 4s

}

mature = 5s

/etc/spread/spread.conf

Spread_Segment 10.8.4.9 {

       hap-1     10.8.4.109

       hap-2     10.8.4.110

}

EventLogFile = /var/log/spread.log

EventTimeStamp