Don't use SSL for default backend(?)

The situation is the following:

HAProxy runs very nicely (amazing piece of software btw. thanks!) for a couple of months already on a load-balancer which has a wildcard DNS entry, let’s say *.foo.org. I have lots of backends and here is the (shortened) configuration:

frontend default
    bind *:80
    bind *:443 ssl crt /etc/ssl/private/

    default_backend no-match

    http-request set-header X-Forwarded-For %[src]
    http-request redirect scheme https code 301 unless { ssl_fc }

    # TODO: this is experimental, to see if ELOG needs it
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
    http-request set-header X-Forwarded-Proto http if !{ ssl_fc }

    reqadd X-Forwarded-Proto:\ https
    option http-server-close

    option forwardfor
    option httpclose

    use_backend stat if { path -i /my-stats }

    acl ACL_lets_encrypt path_beg /.well-known/acme-challenge/
    use_backend be_lets_encrypt if ACL_lets_encrypt

    acl ACL_a.foo.org  hdr(host) -i a.foo.org
    use_backend be_a.foo.org if ACL_a.foo.org

    acl ACL_b.foo.org  hdr(host) -i b.foo.org
    use_backend be_b.foo.org if ACL_b.foo.org

    acl ACL_c.foo.org  hdr(host) -i c.foo.org
    use_backend be_c.foo.org if ACL_c.foo.org

    ...

backend no-match
    mode http
    tcp-request content reject
#    http-request deny deny_status 400

Now the problem is that of course *.foo.org is pointing to the load balancer, but if a user types in a unused domain, e.g. q.foo.org (which should match the default backend no-match) the wrong SSL certificate is loaded. For some reason, the SSL certificate which is presented to the user is corresponding to the second last (valid) domain.

I currently don’t have the possibility to obtain a wildcard certificate, so what do you recommend to avoid the load of any certificate in case no ACLs are matching? Or is there a better way to deal with this situation?

When there is no SNI match the default certificate will be served. You are pointing haproxy to a directory so the default certificate is probably the one that comes first alphabetically.

If you want a different default cert, specify it manually before.

bind *:443 ssl crt /etc/ssl/private/default.pem crt /etc/ssl/private/

You can instruct haproxy to abort the SSL connection in this case, by setting strict-sni:

bind *:443 ssl crt /etc/ssl/private/ strict-sni
1 Like

Thanks Lukas, I just tried and it works, but the problem is that now it still tries to do an HTTPS connection, which of course fails. Is there a way to get a simple HTTP backend for the case that no SSL certificate was matching?

The entire purpose of HTTPS is to not let you get away with an invalid/non-existing certificate, so no, there is absolutely no way. A browser that wants HTTPS either gets it or it fails. You cannot respond with some other protocol, like HTTP, it doesn’t work like that.

You can abort the SSL handshake which is what strict-sni does. That’s it.

I meant if a user connects to HTTP :wink: Currently HAProxy automatically redirects to HTTPS, but I don’t see why.

Haproxy redirects to HTTPS because of this configuration:

http-request redirect scheme https code 301 unless { ssl_fc }

It will always redirect to HTTPS, unless the connection already is HTTPS. If you don’t want to do that, you can make an ACL matching certains hostnames and adjust the behavior based on that.

For example:

acl httpsdomains hdr_dom example.org
acl httpsdomains hdr_dom example.com
acl httpsdomains hdr_dom example.net

http-request redirect scheme https code 301 if { ! ssl_fc httpsdomains }
1 Like