Update: HAProxy can now handle SSL client certificate: SSL Client certificate management at application level
History
HAProxy is well known for its performance as a reverse proxy and load-balancer and is widely deployed on web platforms where performance matters. It is sometimes even used to replace hardware load balancers such as F5 appliances.
When the platform requires SSL, it is common to use Nginx, Pound, or http://www.stunnel.org/index.html. Recently, stud came into the dance with a major advantage over other software: support for HAProxy’s proxy protocol.
At HAProxy Technologies, we build our ALOHA load-balancers using HAProxy, and we use stunnel as the SSL offloading software. Our clients wanted some new features on our SSL implementation we could not provide through stunnel.
By the way, you can find our stunnel patches here: //www.haproxy.com/download/free/patches/stunnel/
Another important thing to notice, is that stunnel does not scale very well: when managing a lot en encrypted connections, stud or nginx are far much better. That’s why we decided to implement SSL directly in HAProxy. For now, it is still quite basic: SSL offloading with SNI support and wildcard certificates ability to encrypt traffic to servers.
But at least the performance is here! We’ll keep on improving it later with new features, IE: client certificate management and some fun stuff with ACLs: stay tuned!
Remember that the job was done by HAProxy Technologies engineers.
Note that if you’re using the softwares listed above for other purpose than SSL, then you may still use them. For example, nginx performs very well on static content and on dynamic using php-fpm.
SSL Offloading Diagram
This is pretty simple, as shown on the picture below. The client will get connected on HAProxy using SSL, HAProxy will process SSL and get connected in clear to the server:
HAProxy Installation
cd /usr/src
wget http://haproxy.1wt.eu/download/1.5/src/devel/haproxy-1.5-dev12.tar.gz
tar xzf haproxy-1.5-dev12.tar.gz
cd haproxy-1.5-dev12/
make TARGET=linux2628 USE_STATIC_PCRE=1 USE_OPENSSL=1
sudo make PREFIX=/opt/haproxy-ssl install
sudo make PREFIX=/opt/haproxy-ssl install
HAProxy Configuration for SSL Offloading
First of all, you have to generate a few keys and certificates using openssl and concatenate them in a file, the certificate first, then the key.
HAProxy configuration for test purposes, and just to let you know which lines are very important:
defaults
log 127.0.0.1 local0
option tcplog
frontend ft_test
mode http
bind 0.0.0.0:8443 ssl crt ./haproxy.pem crt ./certs/ prefer-server-ciphers
# other (self described) options are: [ciphers <suite>] [nosslv3] [notlsv1]
use_backend bk_cert1 if { ssl_fc_sni cert1 } # content switching based on SNI
use_backend bk_cert2 if { ssl_fc_sni cert2 } # content switching based on SNI
default_backend bk_www.haproxy.com
backend bk_www.haproxy.com
mode http
server srvxlc 127.0.0.1:80
backend bk_cert1
mode http
server srv1 127.0.0.1:80
backend bk_cert2
mode http
server srv2 127.0.0.1:80
As you can see, HAProxy load one cert haproxy.pem which will be the default one, and all the certificates from the certs dir. Actually, I have only 2 for my tests: cert1 and cert2.
Running HAProxy
First, just test that the configuration is valid:
/opt/haproxy-ssl/sbin/haproxy -c -f ./hassl.cfg
[WARNING] 247/110924 (6497) : config : missing timeouts for frontend 'ft_test'.
| While not properly invalid, you will certainly encounter various problems
| with such a configuration. To fix this, please ensure that all following
| timeouts are set to a non-zero value: 'client', 'connect', 'server'.
[WARNING] 247/110924 (6497) : config : missing timeouts for backend 'bk_test'.
| While not properly invalid, you will certainly encounter various problems
| with such a configuration. To fix this, please ensure that all following
| timeouts are set to a non-zero value: 'client', 'connect', 'server'.
Configuration file is valid
Don’t worry about warnings, I purposely wrote a very basic configuration.
Now, you can run HAProxy:
/opt/haproxy-ssl/sbin/haproxy -f ./ha.cfg
Testing SSL Provided by HAProxy
Check the default certificate server name:
openssl s_client -connect 127.0.0.1:8443 -servername www.haproxy.com
[...]
Certificate chain
0 s:/CN=www.haproxy.com
i:/CN=www.haproxy.com
[...]
HAProxy log line:
[...] ft_test bk_www.haproxy.com/srvxlc [...]
Checking cert1, loaded from ./certs/ dir:
openssl s_client -connect 127.0.0.1:8443 -servername cert1
[...]
Certificate chain
0 s:/CN=cert1
i:/CN=cert1
[...]
HAProxy log line:
[...] ft_test bk_cert1/srv1 [...]
Checking cert2, loaded from ./certs/ dir:
openssl s_client -connect 127.0.0.1:8443 -servername cert2
[...]
Certificate chain
0 s:/CN=cert2
i:/CN=cert2
[...]
HAProxy log line:
[...] ft_test bk_cert2/srv2 [...]
Checking with an unknown servername:
openssl s_client -connect 127.0.0.1:8443 -servername kemp
[...]
Certificate chain
0 s:/CN=www.haproxy.com
i:/CN=www.haproxy.com
[...]
HAProxy log line:
[...] ft_test bk_www.haproxy.com/srvxlc [...]
When the name is unknown, the failover is well done on the default certificate.
And voilà !!!
Since it has been released in the 1.5 branches, you can use it in production 🙂