olivierg
olivierg

Reputation: 792

HAProxy with SSL passthrough to multiple domains with multiple backends

I need to setup a load balancer for all our applications.

At the moment all our applications are clustered (2-node appservers, and 1 apache on each node as well) and we do not have a LB so we just point our DNS alias to the first webserver of each node, making the second node useless (have to manually do a DNS switch in case of a failure of node1, and we don't have load balanced https queries).

Each application uses SSL with a specific domain & SSL certificate. we cannot accept to decrypt SSL and send unencrypted traffic to the backends as the LB might be located in another country etc. so we need to use passthrough.

Before anything, i just wanted to know if this is actually possible in HAProxy or not ?

I am talking about ~50 different applications. Our LB configuration would have to be HA so i guess we'll use something like keepalived with a shared VIP for HAProxy itself.

The setup would look like this i suppose :

domain-a.com-'            '-> backend_dom_a -> 1.1.1.1 (app node1 dom a)
             |            |                    1.1.1.2 (app node2 dom a)
domain-b.com-'            '-> backend_dom_b -> 2.1.1.1 (app node1 dom b)
             |            |                    2.1.1.2 (app node2 dom b)
domain-c.com-'            '-> backend_dom_c -> 3.1.1.1 (app node1 dom c)
             |            |                    3.1.1.2 (app node2 dom c)
domain-N.com-'            '-> backend_dom_N -> 4.1.1.1 (app node1 dom N)
             |            |                    4.1.1.2 (app node2 dom N)
             +-> haproxy -+

Thanks for your support, best regards

Upvotes: 0

Views: 12441

Answers (3)

olivierg
olivierg

Reputation: 792

FYI i'm using this configuration that works like a charm.

i have replaced the values in the files to hide our domains & hostnames, and limited the numbers of urls/backends but we have about 50 running now with the load balancer forwarding requests to many apache servers (and each apache forwards requests to tomcat servers behind)

feel free if you have any question

we use balance source to ensure session stickyness

#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
    daemon
    user                haproxy
    group               haproxy
    log                 /dev/log local6 notice
    log                 /dev/log local5 info
    maxconn             50000
    #chroot              /var/lib/haproxy
    pidfile             /var/run/haproxy.pid

#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
    mode                 tcp
    option               tcplog
    log                  global
    option               dontlognull
    timeout connect      5000
    timeout client       50000
    timeout server       50000

#---------------------------------------------------------------------
# dedicated stats page
#---------------------------------------------------------------------
listen stats
    mode http
    bind :22222
    stats enable
    stats uri            /haproxy?stats
    stats realm          Haproxy\ Statistics
    stats auth           <mylogin>:<mypass>
    stats refresh        30s

#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend main_https_listen
    bind <ip address>:443
    mode                tcp
    option              tcplog
    log                 global
    tcp-request inspect-delay 5s
    tcp-request content accept if { req.ssl_hello_type 1 }

#---------------------------------------------------------------------
# Common HAProxy nodes configuration
#---------------------------------------------------------------------

# -------------------------------
# ACLs
# -------------------------------

acl acl_SIT_AT35073      req.ssl_sni -i <app_url1>.my.domain.net  # SIT_AT35073 is just an internal code we use, but you can use any alias
acl acl_SIT_AT34305      req.ssl_sni -i <app_url2>.my.domain.net
acl acl_SIT_AT28548      req.ssl_sni -i <app_urlN>.my.domain.net

# -------------------------------
# Conditions
# -------------------------------

use_backend backend_SIT_AT35073 if acl_SIT_AT35073   # same here
use_backend backend_SIT_AT34305 if acl_SIT_AT34305
use_backend backend_SIT_AT28548 if acl_SIT_AT28548

#---------------------------------------------------------------------
# Backends
#---------------------------------------------------------------------

# APP 1
backend backend_SIT_AT35073
    description APPNAME1
    mode tcp
    balance source
    option ssl-hello-chk
    server server_SIT_AT35073_1 <apache_server1>.my.domain.net:443 check
    server server_SIT_AT35073_2 <apache_server2>.my.domain.net:443 check

# APP 2
backend backend_SIT_AT34305
    description APPNAME2
    mode tcp
    balance source
    option ssl-hello-chk
    server server_SIT_AT34305_1 <apache_server3>.my.domain.net:443 check
    server server_SIT_AT34305_2 <apache_server4>.my.domain.net:443 check

# APP N
backend backend_SIT_AT28548
    description APPNAMEN
    mode tcp
    balance source
    option ssl-hello-chk
    server server_SIT_AT28548_1 <apache_server5>.my.domain.net:443 check
    server server_SIT_AT28548_2 <apache_server6>.my.domain.net:443 check

Upvotes: 3

Alex M
Alex M

Reputation: 106

AS more of an update answer for multi domain configs I use the below for routing different domains. in the frontend is where you bind the port and add the certs which multiple have to be on the same line afaik.

 frontend https_in
        bind *:443 ssl crt /link/to/cert+key-file.pem  crt /link/to/cert+key-file.pem

The acl host is where you specify the domain name and which backend to use based on that domain name.

 acl host_example.com hdr(host) -i example.com

 use_backend BACKEND_NAME if host_example.com

The backend where you specify the server that domain is running on.

 backend BACKEND_NAME
    mode http
    option httpclose
    option forwardfor
    cookie JSESSIONID prefix
    server server-name server-ip:443 check ssl verify none

Upvotes: 1

zokkker13
zokkker13

Reputation: 162

I think you have two options:

  1. pass the traffic through to the backend by using the TCP mode in haproxy frontend and backend. This has the benefit that your backend SSL certificate is passed through. Though you lose the possibility to have one SSL termination in your site. So I present you

  2. Have one (usual) SSL certificate, acting as termination for your site and enable SSL between your backend and haproxy instance. This gives you the advantage that you still have only one entry point but different backends with unique certificates.

The second option might look like this:

frontend f_foo
    bind :443 ssl crt /path/to/bundle
    mode http
    log global

    use_backend b2_foo

backend be_foo
    mode http
    timeout connect 5s
    server FOO address:port ssl check crt /path/to/client/bundle force-tlsv10 verify none

The drawback is that you need a client certificate for each backend server but that should be easily automatable.

Upvotes: 1

Related Questions