How to set ssl verify client for specific domain name


Hi, all

I have two domain name test1 and test2
test1 needs to verify client certificate,
test2 is a normal https website

here’s the config for test1, but I don’t know how to merge test2 to it becase test2 does not need to verify client certificate, seems ‘verify required’ is a global option, how can I just let test1 to verify client certificate? Thanks for the help (I’m new to HAProxy, please correct me if anything wrong in my config, thanks a lot.).

frontend http_in
        bind *:80
        bind *:443 ssl crt /etc/ssl/certsforhaproxy/test1.pem crt /etc/ssl/certsforhaproxy/test2.pem ca-file /etc/ssl/certsforhaproxy/ca.pem verify required
        redirect scheme https if !{ ssl_fc }
        acs host_test1 hdr_beg(host)
        acs host_test2 hdr_beg(host)
        use_backend test1_back if host_test1
        use_backend test2_back if host_test2

backend test1_back
        mode http
        default-server inter 2s fall 2 rise 2
        server node1 check port 1234
        server node2 check port 1234
        server node3 check port 1234

backend test2_back
        mode http
        default-server inter 2s fall 2 rise 2
        server node1 check port 2345
        server node2 check port 2345
        server node3 check port 2345


Only thing I can think of right now is to set the verify to optional so clients can connect with or without the client certificate and then restrict access using an ACL like so:

acl restricted hdr(host) -i
http-request deny if restricted ! { ssl_c_used }


There is no simple way to do this, unfortunately.

Use a TCP frontend withouth SSL termination, SNI route to different backends that recirculate to traffic to dedicated SSL frontends with different configurations.

Something like:

frontend port443
    bind :443
    tcp-request inspect-delay 5s
    tcp-request content accept if { req_ssl_hello_type 1 }
    use_backend recir_clientcertenabled if { req_ssl_sni -i }
    default_backend recir_default

backend recir_clientcertenabled
    server loopback-for-tls abns@haproxy-clientcert send-proxy-v2
backend recir_default
    server loopback-for-tls abns@haproxy-default send-proxy-v2

frontend fe-ssl-clientcert
    mode http
    bind abns@haproxy-clientcert accept-proxy ssl crt /etc/ssl/certsforhaproxy/test1.pem crt ca-file /etc/ssl/certsforhaproxy/ca.pem verify required
frontend fe-ssl-default
    mode http
    bind abns@haproxy-default accept-proxy ssl crt /etc/ssl/certsforhaproxy/test2.pem crt

Use haproxy with http2 backends and non http2 backends
Different SSL Protocols for each backend server. Is it possible?

Improvement to my answer…

Set the verify option on the bind line to “optional” and use the following ACL:

acl restricted hdr(host) -i
http-request deny if restricted !{ ssl_c_used 1 } || restricted !{ ssl_c_verify 0 }

The above simply says if the header host matches a specific domain deny request unless the client has provided a certificate and that certificate was verified.

You can improve on this by adding specific error pages, example:

redirect location /certmisiing.html if restricted !{ ssl_c_used 1 }
redirect location /certexpired.html if restricted { ssl_c_verify 10 }
redirect location /certrevoked.html if restricted { ssl_c_verify 23 }
redirect location /othererrors.html if restricted !{ ssl_c_verify 0 } 

I even wrote a Blog on the subject, hope that helps:


“verify optional” has a rather important disadvantage: it changes the SSL handshake, leading to different browser behavior for all of the websites.

For example, if you have a browser with a client certificate installed for a unrelated domain, and haproxy handles and, the browser will ask you for both and if and which client certificate you wanna send.

While this is expected behavior for it isn’t for

By SNI routing to different SSL termination endpoints like suggest above we avoid this problem. We also have a “proper” SSL handshake failure with “verify required”, instead of failure on the HTTP layer.


Thanks Lukas, I found this also in my testing, I was very much playing and reverse engineering how it works learning lots of new stuff for the first time. Yesterday I referenced your better solution with SNI in my Blog, I hope that’s okay, I gave you credit and linked it back here.