For some reason I get “503 Service Unavailable” when trying to reach a backend server over 443/ssl where the target server uses wildcard SSL in their Subject Alternative Names. Here’s the full config you can test out to verify. It works when trying to reach backend without SSL or with SSL that doesn’t use wildcards. See comments in backend sections. How can I make it work with backend sites that uses wildcard SSL?
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
frontend http-in
bind *:80
bind *:443 ssl crt /root/cert.pem
default_backend app6
# this works when backend server on port 80 but fails on 443
# https://10.10.1.111/data/validatorstats.json
# cert uses wildcard
backend app1
http-request set-header Host defier.net
server server1 defier.net:443 ssl verify none
# server server1 defier.net:80 check
# this works: https://10.10.1.111/document/txt/example.txt
# cert is not using wildcard
backend app2
http-request set-header Host example-files.online-convert.com
server server2 example-files.online-convert.com:443 ssl verify none
# this fails: https://10.10.1.111/
# cert uses wildcard
backend app3
http-request set-header Host osmosisarchive-rpc.quickapi.com
server server3 osmosisarchive-rpc.quickapi.com:443 ssl verify none
# this fails: https://10.10.1.111/
# cert uses wildcard
backend app4
http-request set-header Host osmosis-rpc.polkachu.com
server server4 osmosis-rpc.polkachu.com:443 ssl verify none
# this fails: https://10.10.1.111/sample.txt
# cert uses wildcard
backend app5
http-request set-header Host txt2html.sourceforge.net
server server5 txt2html.sourceforge.net:443 ssl verify none
# this works: https://10.10.1.111/
# cert is not using wildcard
backend app6
http-request set-header Host thetestdata.com
server server6 thetestdata.com:443 ssl verify none
You almost certainly need to send SNI to some of those servers, so they actually respond.
You do this by adding sni str(example.org)
:
backend app5
http-request set-header Host txt2html.sourceforge.net
server server5 txt2html.sourceforge.net:443 ssl sni str(txt2html.sourceforge.net) verify none
Wow that worked! Thank you! I’m not familiar with sni but will read up some more on it and see why it’s needed by some servers. I’m guessing it’s a security feature
It’s basically sending the hostname your are trying to connect in the first SSL message (client_hello), so that the server knows which certificate to send you, when it has multiple.
@lukastribus That makes sense. Thank you! Would you happen to know how to enable health checks with SSL? I tried different combinations but can’t get it to work. with “verify none” my page works but not checking health. But if I do “verify required” then it says I’m missing the cert. But I already specified the pem file in the frontend. Any suggestions?
backend app1
balance roundrobin
http-check expect status 200
option ssl-hello-chk
http-request set-header Host defier.net
server server1 defier.net:443 ssl verify none sni str(defier.net) verifyhost defier.net check-sni defier.net
Don’t use option ssl-hello-chk, that’s an old options that just mimics are SSLv3 client hello, this is not gonna work.
Just add the check keyword also with specifying the sni with check-sni
Now if you want to verify the server certificate (verify required), than you need to specify not the certificate but the certificate authority root file.
As per verify:
The certificate provided by the server is verified using CAs from ‘ca-file’ and optional CRLs from ‘crl-file’ after having checked that the names provided in the certificate’s subject and subjectAlternateNames attributes match either the name passed using the “sni” directive, or if not provided, the static host name passed using the “verifyhost” directive.
So you need to configure the ca root files, for example by refering to the system-ca as per ca-file
@lukastribus
I don’t want to verify the cert since I trust it. So I’ll keep “verify none”.
I tried adding check keyword with check-sni but it doesn’t seem to do anything. I added “check port 443” and that seems to verify port 443 is open which is good. But one last thing I can’t figure out is how to get it to check for status 200 for health check. I have “http-check expect status 200” but it seems ignored. But if I add “option httpchk” then it always fails. So not sure what to do from here to get it to verify 200 response over SSL backend site. I feel like I’m really close and it’s something simple but I haven’t found one that works. See below for what I have so far. The port 443 check works but not the “http-check expect status 200” doesn’t work.
balance roundrobin
http-check expect status 200
http-request set-header Host defier.net
server defier.net defier.net:443 ssl verify none sni str(defier.net) check port 443 check-sni defier.net
You need need “port 443” when the configuration already points to 443.
I think you are only missing a option httpchk
in the backend.