I am working on an HAProxy server configuration for a proof of concept. We want to forward any incoming connections which either

Have a successful 2-way TLS handshake or

Are coming from an IP address in a whitelist

I was looking at the documentation on ACLs, and thought maybe I could configure one to check for certs and one to check the whitelist, but I’m not sure if I’m barking up the right tree here. Currently, I have a server accepting valid certs by binding a port with an SSL certificate like so: bind *:2000 ssl crt cert.pem ca-file myCA.pem verify required

Another idea i’ve had is redirecting to a second port in case of failure on the first one. So, for instance, if the handshake fails, we redirect to another port checking a whitelist, or vice versa.

Which of these seems like a better approach? Are either of them impossible to implement in HAProxy? Thank you for any assistance.

In a perfect world, you would just set “verify” to optional, and handle everything else with ACL’s.

However, that means that a browser in the whitelisted IP range may ask the customer as well which client certificate to send (if the browser has a client certificate). You probably want haproxy to act normal for the whitelisted IP’s, and only signal the intend to authenticate a client certificate when the customer is not whitelisted.

To do that, you need a little trick, basically a TCP frontend that checks the source IP and reoutes the TCP traffic to a client cert frontend or a “normal” frontend.

Hey, thanks for the reply. This is similar to the idea I had in my mind for the second option, which I’ve been playing around with. I have a few questions about it.

First, what are bind abns@haproxy-clientcert... and bind abns@haproxy-default... doing? I only know how to bind to an IP:port.

Second, are you using fe-ssl-default to handle regular SSL connections (as in, only the client is verifying the server, not 2-way). If so, what exactly is in test2.pem, and what does the client need to access the service that way?

Finally, this proxy is (eventually) going to be used for forwarding to another https site. Will it be a problem to have two different SSL connections in the chain? Can HAProxy handle that?

First, what are bind abns@haproxy-clientcert… and bind abns@haproxy-default… doing? I only know how to bind to an IP:port.

Those are abstract namespaces, think of it like sockets, but neither with an IP:port, nor with a filesystem dependency (as it is for unix domain sockets).

Sounds complicated, but it isn’t. This configuration just connects the backend with the lower layer frontend.

You can easily replace this with 2 TCP ports on 127.0.0.1.

jared.dembrun:

Second, are you using fe-ssl-default to handle regular SSL connections (as in, only the client is verifying the server, not 2-way). If so, what exactly is in test2.pem, and what does the client need to access the service that way?

I just copy and pasted the base config from another example where we actually had different certificates.

In your case both would be “crt both.pem”.

jared.dembrun:

Finally, this proxy is (eventually) going to be used for forwarding to another https site. Will it be a problem to have two different SSL connections in the chain? Can HAProxy handle that?

You can do that, you just have to re-encrypt on the backend (use the ssl keyword on the backend and configure ca validation with the “verify” and the ca-file keyword (this is different than your frontend client certificate authentication).

But, when I run this, I get [ALERT] 284/153320 (57243) : Starting frontend fe-ssl-clientcert: cannot bind UNIX socket [] and [ALERT] 284/153320 (57243) : Starting frontend fe-ssl-default: cannot bind UNIX socket [] I’m running this on a mac, so UNIX. Is there something else I need to configure to use the abstract namespaces you mentioned?

It works by binding on 127.0.0.1, but I would like to use the abns if possible so the app isn’t exposed on these other ports.