LinuxLoad Balancing

Set up HAProxy HTTPS – Load balance Over HTTPS Connections

In our first guide on how to set up HAProxy, we were lazy. When we set up HAProxy we didn’t use any SSL Certificates and let CloudFlare do all of the work. You will want to deal with HTTPS connections over your HAproxy load balancer in some situations. HAProxy HTTPS provides two options to deal with secure connections.

* HAProxy SSL Passthrough

SSL Passthrough does what it says, it takes the connection and throws it to a backend server to decrypt. This could be considered faster but has many drawbacks like hiding the client’s true IP. That’s because we don’t decrypt the data as it passes through the load balancer.

* HAProxy SSL Termination

With SSL Termination, HAProxy decrypts the connection as it hits the load balancer and then either encrypts it again to send on to a backend server or just sends the data in an unencrypted fashion. This is considered the default choice but it depends on how you are using HAProxy with HTTPS connections.

Set up HAProxy SSL Termination

We have created this guide based on a specific use case. Our customer has a need for a High Availability MySQL Cluster. In a previous article, we created a network of MySQL servers. We have 5 servers in our cluster running Master-Master MySQL Replication. We now need to configure HAProxy to distribute the load over our cluster. This will provide High Availability. Because our cluster is using Cloudflare under “SSL Full” we installed a Cloudflare Origin certificate on our NGINX cluster. Now we are going to configure HAProxy to work with our Cloudflare Origin Certificate too.

HAProxy SSL Certificate

This next step assumes you have your Cloudflare Origin certificate or any other valid certificate on your server. We combined the origin certificate and private key into one file located at /etc/ssl/cert.pem. Open up the /etc/haproxy/haproxy.cfg file. Replace with the following.

frontend http_front
   bind :80
   bind :443 ssl crt /etc/ssl/cert.pem
   default_backend be_d1

backend be_d1
   balance leastconn
   server S1FR xx.xx.xx.xx:443 check ssl verify none
   server S2UK xx.xx.xx.xx:443 check ssl verify none
   server S3DE xx.xx.xx.xx:443 check ssl verify none
   server S4CA xx.xx.xx.xx:443 check ssl verify none
   server S5USAW 1xx.xx.xx.xx:443 check ssl verify none

global
        log /dev/log    local0
        log /dev/log    local1 notice
#       chroot /var/lib/haproxy
        stats socket /run/haproxy/admin.sock mode 660 level admin
        stats timeout 30s
        user haproxy
        group haproxy


        
#   ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
#        ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
#        ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

defaults
        log     global
        mode    http
        option  httplog
        option  dontlognull
        timeout connect 5000
        timeout client  50000
        timeout server  50000
        errorfile 400 /etc/haproxy/errors/400.http
        errorfile 403 /etc/haproxy/errors/403.http
        errorfile 408 /etc/haproxy/errors/408.http
        errorfile 500 /etc/haproxy/errors/500.http
        errorfile 502 /etc/haproxy/errors/502.http
        errorfile 503 /etc/haproxy/errors/503.http
        errorfile 504 /etc/haproxy/errors/504.http

listen stats
    bind xx.xx.xx.xx:1936 ssl crt /etc/ssl/cert.pem
    mode http
    stats enable
    stats hide-version
    stats show-node
    stats realm Haproxy\ Statistics
    stats uri /haproxy?stats
    stats admin if TRUE
    stats auth User:Pass

So, here we can see we are listening for connections on both port 80, insecure. But also on port 443, secure. Note, that we have specified our Cloudflare Origin certificate in the statement.

bind :443 ssl crt /etc/ssl/cert.pem

In the backend be_d1 block, we specify our backend servers. But notice how we append a secure port to the IPs.

backend be_d1
   balance leastconn
   server S1FR xx.xx.xx.xx:443 check ssl verify none
   server S2UK xx.xx.xx.xx:443 check ssl verify none
   server S3DE xx.xx.xx.xx:443 check ssl verify none
   server S4CA xx.xx.xx.xx:443 check ssl verify none
   server S5USAW 1xx.xx.xx.xx:443 check ssl verify none

HAProxy HTTPS SSL Certificate

The important bit here is the ssl verify none. Connections are encrypted again before being sent on to the backend servers. Without this, we would see an error about insecure connections being sent to a secure port. We are using the same certificate on HAProxy as on our cluster. Finally, restart the cluster.

systemctl restart haproxy

In this example, HAProxy statistics can be viewed at http://IPv4:1936/haproxy?stats. So if we take a look we can see HAProxy HTTPS is routing connections to our backend server.

HAProxy HTTPS Connections

We can further confirm this over https. Our HAProxy URL is https://dgb-ha.dev.gb.net. So, give it a try, you will be routed to one of the backend servers over a secure connection. Refresh the page after 30 seconds to be sent to a different backend server.

load balance https haproxy

So, in our final guide, we will load balance MySQL connections using HAProxy. Once complete we will have a high availability cluster running MySQL, PHP, NGINX.

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button