Mascote

notes to self.

Setting Up a Load Balancer Using Apache 2.4

UPDATE: Actualy my point about 2way ssl just on one location is wrong here. There is no sense in send the CA just to one location because of the basics of the HTTP protocol, first the connection is established, then the HTTP method is issued, so sending the CA is required at the SSL handshake.

The load balancing part still valid anyway. :)


On a high available architectures is common to use HAproxy to load balance request accross a set of application servers, sometimes we Sysadmins need to setup not so common features where we need to be aware about all others software in the stack, for example when you need to secure an expecific URI using 2way/mutual authentication where is used a client ssl certificate to authenticate access to a determined service.

This setup can be tricky because there is some pitfalls when using HAproxy and Apache:

  • you need to pass the ssl traffic through tcp to the backends
  • have to configure ssl directly on each application instance
  • use the PROXY protocol to have the information about the client ip address
  • deploys can break existing established connections

I can't setup 2way ssl directly on HAproxy because the verify option is global at the listen directive, neither on Nginx because they don't provide the possibility to have diferent verify levels on diferent locations.

To avoid these quirks and keeping my configuration as simple as possible I discovered the load balancing option on apache documentation allowing me to setup my virtual host with both 2way ssl and load balancing as shown below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  <VirtualHost _default_:443>
    ServerAdmin webmaster@example.com

    DocumentRoot /var/www/foo

    LogLevel error

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    SSLEngine On
    SSLProxyEngine On

    SSLCertificateFile    /etc/apache2/ssl/cert.pem
    SSLCertificateKeyFile /etc/apache2/ssl/key.pem
    SSLCACertificateFile  /etc/apache2/ssl/ca-combined.pem

    ProxyPreserveHost On

    <Proxy balancer://default>
      BalancerMember http://app01:8080
      BalancerMember http://app02:8080
      BalancerMember http://app03:8080
      BalancerMember http://app04:8080
    </Proxy>

    # <Location /my_secure_location>
    #   SSLVerifyClient require
    #   SSLVerifyDepth  1
    #   SSLRequireSSL

    #   ProxyPass balancer://default/
    #   ProxyPassReverse balancer://default
    # </Location>

    <Location />
      ProxyPass balancer://default/
      ProxyPassReverse balancer://default
    </Location>

  </VirtualHost>

This configuration combined with Ansible loops provides a good automation strategy also keeping backend and load balancer configuration simple.

I'm using with the evented apache module to have the same benefits as the non-blocking Nginx reactor pattern, so is pretty fast.

I provided an Ansible role with the complete configuration on this repository.