To replicate my results:

Generate 3 ssl certificates (letsenc? I used a dns-01 challenge...)..

default.example.ca
working.example.ca
should-be-broken.example.ca

Configure an apache instance to serve only the first two via https. default.example.ca and working.example.ca; don't configure any virtualhost for should-be-broken.example.ca.

Configure the haproxy instance with all 3 certificates in the haproxy format with the intermediates and private keys included in a single file. Name the files like default.example.ca.pem, working.example.ca.pem, should-be-broken.example.ca.pem and toss em in /etc/haproxy/certs...

Install the ca-certificates package if you're on debian/ubuntu (otherwise adjust the ca-certificates location to whatever distro you're running)...

Then:

haproxy.cfg:

frontend www-https
bind :::443 v4v6 ssl crt /etc/haproxy/certs/default.example.ca.pem crt /etc/haproxy/certs/
    use_backend www-backend-https

backend www-backend-https
server app default.example.ca:443 ssl verify required sni ssl_fc_sni ca-file /etc/ssl/certs/ca-certificates.crt check check-ssl

If you visit https://should-be-broken.example.ca you will get the page for default.example.ca, but the browser/visitor will show the should-be-broken.example.ca cert from the haproxy and the page will appear secure, despite the backend apache instance having no access to should-be-broken's virtual host or certificate and serving a certificate for default.example.ca to the haproxy.

--
Kevin




On 2017-07-24 3:25 PM, Kevin McArthur wrote:

Hi Willy,

I can confirm the following line does _not_ verify the hostname on the backend.

server app2 ssltest.example.ca:443 ssl verify required sni ssl_fc_sni ca-file /etc/ssl/certs/ca-certificates.crt check check-ssl

I setup a default https vhost on the backend server, that responds to ssltest.example.ca ... in the above configuration the health checks pass and if you visit a sni-configured site (otherhost.example.ca) it will also work. However, you load another SNI virtualhost that only the haproxy has a cert for but for which the backend responds with a mismatching ssltest certificate, it will happily load that site, present it as TLS protected to the web browser and *NOT check the verifyhost against the backend SNI. *

That is to say, without verifyhost <something> no hostname verification is done between the haproxy and the cert presented by the backend and any valid certificate (even the default-configured ssltest one) will work on the backend.

--

Kevin McArthur


On 2017-07-23 9:40 PM, Willy Tarreau wrote:
Hi Kevin,

On Fri, Jul 21, 2017 at 02:06:52PM -0700, Kevin McArthur wrote:
Further... the odd/broken behavior might be being caused related to no sni
indication on the health checks...

This config sort of works:


*server app2 ssltest.example.ca:443 ssl verify required /verifyhost
ssltest.example.ca/ sni ssl_fc_sni ca-file
/etc/ssl/certs/ca-certificates.crt check check-ssl*

This lets me load ssltest.example.ca via the proxy.


*server app2 anotherdomain.example.ca:443 ssl verify required /verifyhost
anotherdomain.example.ca/ sni ssl_fc_sni ca-file
/etc/ssl/certs/ca-certificates.crt check check-ssl*

Jul 21 20:57:55 haproxy1 haproxy[8371]: Health check for server
www-backend-https/app2 failed, reason: Layer6 invalid response, info: "SSL
handshake failure", check duration: 3ms, status: 0/2 DOWN.

Fails health check (no sni) verifyhost match (anotherdomain.example.ca isnt
the default on the backend server). So ends up in "No server is available to
handle this request."


*server app2 ssltest.example.ca:443 ssl verify required /verifyhost
ssl_fc_sni/ sni ssl_fc_sni ca-file /etc/ssl/certs/ca-certificates.crt check
check-ssl*

Jul 21 20:57:55 haproxy1 haproxy[8371]: Health check for server
www-backend-https/app2 failed, reason: Layer6 invalid response, info: "SSL
handshake failure", check duration: 3ms, status: 0/2 DOWN.

This fails health check.


*server app2 ssltest.example.ca:443 ssl verify required sni ssl_fc_sni
ca-file /etc/ssl/certs/ca-certificates.crt check check-ssl*

This works, but without verifying the host properly. Can load
anotherdomain.example.ca and the sni is passed along properly.


Perhaps its the host checks sni support and not this patch that are not
working correctly?
The "verifyhost" directive *forces* the host name to be checked and ignores
the SNI. By just removing it from your "server" lines, it must be OK. Your
last example above suggests it works. Why do you say that the host is not
properly verified ? Have you checked that you can connect to a server
presenting the wrong cert ? For me it refuses it and only accepts the
correct cert (the one having the same name as asked in the SNI).

Willy


Reply via email to