How to deliver certificate randomly to browser, according to the backend IP/server picked by HAProxy?

Hi,

I am a beginner in HAProxy and I was trying to achieve this. I have 4 VMs, one having HAProxy server and Apache httpd server in other 3 VMs. I have test.html on all three servers. When user hit https://haproxy_ip/test.html, the file may be delivered from any server.

I have generated separate SSL certificate in each VM (by referring these urls How to enable https on Apache CentOS - TechRepublic and https://www.suse.com/support/kb/doc/?id=000018152) and copied the pem and key files to HAProxy VM. Now, all three pem files are available under /etc/haproxy/ directory.

I have configured ssl crt-list to pick corresponding SSL certificate by HAProxy, and below is how crt-list.txt looks like;

/etc/haproxy/testserver1.pem testserver1
/etc/haproxy/testserver2.pem testserver2
/etc/haproxy/testserver3.pem testserver3

What I am looking for is, when user request https://haproxy_ip/test.html in browser, the certificate that need to be delivered each time should be based on the backend server picked by HAProxy.

Is this possible / supported by HAProxy? If yes, can somebody please help me?

Below is my current configuration;

global
    maxconn 50000
    log /dev/log local0
    log /dev/log local1 notice
    user root
    group root
    stats timeout 30s
    nbproc 2
    cpu-map auto:1/1-4 0-3
    ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
    daemon

defaults
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms

frontend ft_http
    bind :80
    mode http
    default_backend bk_http

frontend ft_https
    bind :443 ssl crt-list /etc/haproxy/crt-list.txt
    mode tcp
    default_backend bk_https

backend bk_http
    mode http
    balance roundrobin
    default-server inter 1s
    server testserver1 192.168.0.1:80 check
    server testserver2 192.168.0.2:80 check
    server testserver3 192.168.0.3:80 check

backend bk_https
    mode tcp
    balance roundrobin
    stick-table type ip size 200k expire 1m
    default-server inter 1s
    server testserver1 192.168.0.1:443 check
    server testserver2 192.168.0.2:443 check
    server testserver3 192.168.0.3:443 check

Thanks in advance… :pray:

That doesn’t make a lot of sense, and no, it is not possible in this configuration. Can you explain why you would want to achieve this so that we cannot suggest a better solution?

Hi @lukastribus thanks for your reply. Let me explain the scenario.

Say, I have two customers (two different domains) and they put DNS entries CNAME, so that when user enter https://myapp.customer1.com or https://myapp.customer2.com in browser, it redirects to my server, where I have HAProxy in place. Also, lets say the customer is not storing / not willing to store subdomain certificate in his server due to some reason. In that case, I need to store and maintain those certificates in my server. Since both customers use different server, I cant use wildcard certificates. Also, lets say I don’t prefer SANS either.

In this scenario, how can I deliver corresponding certificate (according to domain user requested) from my server using HAProxy? Hope you understand what I am trying to achieve.

You want haproxy to serve the appropriate certificate, based on what the browser requests.

This will already happen by default, however I strongly suggest you stop manuall configuring sni values with a crt-list filter. Just let haproxy do this please.

And then, just use the actual hostnames when accessing haproxy. If you use the IP address instead of the hostname, haproxy doesn’t know which hostname you intend to serve, so it will delivery the default certificate, which is the first one.

1 Like

@lukastribus thank you so much. I have 4 linux VMs to test this. Is there any step by step guide or documentation available to setup this?

In the crt-list, stop using snifilters, so just specify the files:

/etc/haproxy/testserver1.pem
/etc/haproxy/testserver2.pem
/etc/haproxy/testserver3.pem

This will make it so that the correct certifcate is delivered. You can also just specify each certificate on the bind line with crt.

This is the exact opposite of what you asked in the first post: you want to load-balance between different backend servers. Now you are saying that you want different customers which certainly need to stick to a server.

Can you just describe what you really want to do?

1 Like

@lukastribus sure, let me explain the scenario.

Lets say, I have an application in AWS, a web app, that I need to deliver to different subdomains. In short, my application need to be available at https://myapplication.domainname1.com, https://myapplication.domainname2.com, https://myapplication.domainname3.com etc…

For each subdomain, an appropriate certificate need to be created and is created and maintained by my AWS Certificate Manager. I will attach this certificate to my Application Load Balancer, and everything works well.

The problem is, Application Load Balancer can hold a maximum of 25 certificates. For every 25 subdomain, I need to bring up a new ALB. I am trying to solve the problem using HAProxy by attaching all certificates to HAProxy, so that it can deliver appropriate certificate automatically.

Hope you understood what I am trying to achieve.

If there is no difference between one domain and the other, then just add the certificates.

If there is a difference in expected behavior from the load-balancer between the domains, explain what that difference actually is.