9

I need to configure HAProxy with two different SSL-Certificates

  1. www.example.com
  2. api.example.com

Now I learned from a post on serverfault ( Configure multiple SSL certificates in Haproxy ) how to use 2 certificates, however the server continues to use the first certificate mentioned for both domains.

Config:

frontend apache-https
    bind 192.168.56.150:443 ssl crt /certs/crt1.pem crt /certs/cert2.pem
    reqadd X-Forwarded-Proto:\ https
    default_backend apache-http

backend apache-http
    redirect scheme https if { hdr(Host) -i www.example.com } !{ ssl_fc }
    redirect scheme https if { hdr(Host) -i api.example.com } !{ ssl_fc }
    ...

How to tell HAProxy which certificate to use depending on the URL?

Full config:

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
    daemon

    # Default SSL material locations
    ca-base /etc/ssl/certs
    crt-base /etc/ssl/private

    ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
    ssl-default-bind-options no-sslv3
    tune.ssl.default-dh-param 2048 // better with 2048 but more processor intensive

defaults
        log     global
        mode    http
        option tcplog
        option  dontlognull
        timeout connect 5000
        timeout client  50000
        timeout server  50000

frontend apache-http
        bind 0.0.0.0:80
        mode http
        option http-server-close                # needed for forwardfor
        option forwardfor                       # forward IP Address of client
        reqadd X-Forwarded-Proto:\ http
        default_backend apache-http
        stats enable

frontend apache-https
        bind 0.0.0.0:443 ssl crt cer1.pem cert2.pem
        reqadd X-Forwarded-Proto:\ https
        default_backend apache-http

backend apache-http
        redirect scheme https if { hdr(Host) -i db.example.com } !{ ssl_fc }
        redirect scheme https if { hdr(Host) -i api2.example.com } !{ ssl_fc }
        balance roundrobin
        cookie SERVERID insert indirect nocache
        server www-1 10.0.0.101:80 cookie S1 check
        server www-2 10.0.0.102:80 cookie S2 check
        server www-3 10.0.0.103:80 cookie S3 check
merlin
  • 2,033
  • 11
  • 37
  • 72
  • Can you post your full config? – GregL Sep 11 '15 at 12:31
  • sure. I have updated the quesiton. – merlin Sep 11 '15 at 12:49
  • In the snipped config above, you list two `crt` directives on your `bind` line, but in the full config you've only got one... Is that intended? Does that cert have SAN entries or is it a wildcard? – GregL Sep 11 '15 at 12:52
  • sorry my mistake, I took the config after I removed the line. My goal is to allow individual ssl certs for individual domains and I am pretty new to HAProxy. Added the second cert in the config listed above. – merlin Sep 11 '15 at 12:55
  • What client are you using where it's providing the wrong cert? – GregL Sep 11 '15 at 12:59

2 Answers2

10

Ensure that you're running HAProxy 1.6 or higher

This question is a little old, but I ran into this exact same issue with configurations similar to the OP.

HAProxy 1.5 accepts the multiple crt syntax on a bind option; however, it uses only the first certificate when responding.

HAProxy 1.6 appears to respond with the certificate based on the caller's request. This does not appear to require any special sni ACLs in the config.

Here's an example that works on 1.6, but fails to use cert2.pem when responding to requests for place2.com on 1.5:

frontend http-in
        bind *:80
        bind *:443 ssl crt cert1.pem crt cert2.pem
        mode http

        acl common_dst hdr(Host) -m str place1.com place2.com

        use_backend be_common if common_dst

backend be_common
        # nothing special here.
davidzarlengo
  • 243
  • 2
  • 7
2

How are you testing which certificate haproxy is presenting? If you're using openssl s_client, be advised that it requires an additional parameter (-servername api.domain.com) in order to send the SNI information which haproxy needs to decide which certificate to present.

womble
  • 95,029
  • 29
  • 173
  • 228
  • I am not sure if I understand your answer. The example mentioned above uses the line: use_backend bk_cert1 if { ssl_fc_sni my.example.com } however I am unsing one backend for both and configure apache to distinguish based on URL what to do. Are multiple SSL certs possible with one backend? – merlin Sep 11 '15 at 06:37
  • 1
    Yes, you don't understand my answer. I'm doubtful of your testing methodology, not your current configuration. – womble Sep 11 '15 at 06:39
  • Well as far as I understand there is not much testing in the config I presented. The only thing that it does test is if the specified domain has gone through https or not and if not it redirects to https. But this is not the question. I am wondering how to dedicate specific certificates to a coresponding URL. – merlin Sep 11 '15 at 06:44
  • 3
    "however the server continues to use the first certificate mentioned for both domains" -- what is the basis for this assertion in your question, if not your own testing? – womble Sep 11 '15 at 09:35