Haproxy as reverse HTTPS proxy

Hello Experts,

I want to configure Haproxy to encapsulate incoming HTTP traffic into HTTPS having an HTTPS backend.
My config looks like this:

frontend http-in-proxy
bind *:80
acl valid_url hdr_end(host) -i mydomain.com
use_backend servers-proxy if valid_url
default_backend forbidden

backend forbidden
mode http
http-request deny deny_status 403

backend servers-proxy
server server1-proxy 10.1.31.15:443 ssl verify none

This works, but I’m not sure if haproxy validates the server certificates when making connection (when it acts as HTTPS Client).

Is there a way to validate the server certs here?

Thanks!

Instead of ssl verify none you specify ssl verify required verifyhost www.example.org ca-file /path/to/backend-ca-certificates.crt

Should crt be the public key only?

I don’t have the private key on the haproxy node.
Also I don’t want to specify one domain since in my backend I may have multiple vhosts. How can this be configured?

I needs to be the public key(s) of the CA(s).

If you can’t have a static value, starting with haproxy 1.8 the used SNI value is used for certificate verification as well, which can be set based on the host header for example.

So remove verifyhost and set SNI, but remember you need haproxy 1.8 for this.

ssl verify required sni req.hdr(host) ca-file /path/to/backend-ca-certificates.crt

Thanks a lot , I will test this with 1.8 version.
Having the list of domains I can fetch the certs and periodically update the crt file with a small script.

You should really put the CA in there instead of single certificates.

I have configured this and retrieved the CA certs using the following command:
openssl s_client -host HOSTNAME.COM -port 443 -prexit -showcerts

But it does not work. I get >

  • Empty reply from server

Let’s make a test:

From the haproxy box, use curl and access the backend, by using the ca-file you just generated:

curl -v --with-ca-bundle=/path/to/backend-ca-certificates.crt https://HOSTNAME.COM/

curl -v --cacert /etc/haproxy/ca.crt https://hostname

  • Rebuilt URL to: https://hostname/
  • Trying IP…
  • Connected to hostname (IP) port 443 (#0)
  • found 3 certificates in /etc/haproxy/ca.crt
  • found 0 certificates in /etc/ssl/certs
  • ALPN, offering http/1.1
  • SSL connection using TLS1.2 / ECDHE_RSA_AES_128_GCM_SHA256
  • server certificate verification OK
  • server certificate status verification SKIPPED
  • common name: *dmain (matched)
  • server certificate expiration date OK
  • server certificate activation date OK
  • certificate public key: RSA
  • certificate version: #3

This is the backend config:
backend http-proxy-backend
server backend hostname:443 ssl verify required verifyhost hostname ca-file /etc/haproxy/ca.crt

Ok, so this seems to work.

Share the details of the failure with haproxy please? What does a curl -v call against haproxy output exactly (and please put it into code format using the </> button above)? Share the haproxy log also.

Try my proposal from above (remeber using haproxy 1.8):

ssl verify required sni req.hdr(host) ca-file /etc/haproxy/ca.crt

Updated to 1.8 version and changed the config.

curl -v http://hostname
* Rebuilt URL to: http://hostname/
*   Trying IP...
* Connected to hostname (IP) port 80 (#0)
> GET / HTTP/1.1
> Host: hostname
> User-Agent: curl/7.47.0
> Accept: */*
>

3 sec delay here

* Empty reply from server
* Connection #0 to host hostname left intact
curl: (52) Empty reply from server

The haproxy log does not show anything useful, probably I need to turn debug mode on.

The pcap teace shows following: Description: Unknown CA (48)
Trying to get debug log.

Problem was solved after I used /etc/ssl/certs/ca-certificates.crt in haproxy config, instead of the ca.crt file which had only certs for my domain.

Thanks a lot!