HTTPS via external (same network) HAProxy

I’ve deployed firezone (0.6.4) using docker (on alpine). no issues seen with install.

The internal network is behind HAProxy (multiple internal hosts and expensive public addresses), so this was configured with a host header ACL for HTTP traffic, and with SNI for HTTPS (51820 is natted directly).

I’m happy that the host header part on HTTP works as firezone gets a LetsEncrypt cert, and firezone is accessible inside the network on HTTPS using the LetsEncrypt cert. Also added AzureAD OpenID auth, which was impressively easy!

Traffic from outside the network on HTTPS is however problematic, while HAProxy checks are fine, actual traffic over HAProxy fails with a 503 (No server is available to handle this request).

HAProxy config is using SNI with proxy protocol to pass the original host address through to the backend, which is re-encrypted to the caddy instance started by the docker compose. Reduced down to just two hosts to show the method, the HAProxy HTTPS config looks like the below (the same SAN LetsEncrypt cert is used for all hosts in HAProxy).

frontend sni-front
        bind 192.168.101.80:443
        mode tcp
        tcp-request inspect-delay 5s
        tcp-request content accept if { req_ssl_hello_type 1 }
        default_backend sni-back

backend sni-back
        mode tcp
        acl mc-sni req_ssl_sni -i meshcentral.domain.net
        acl wg-sni req_ssl_sni -i firezone.domain.net
        use-server mc-SNI if mc-sni
        use-server wg-SNI if wg-sni
        server mc-SNI 192.168.101.80:1443 send-proxy-v2-ssl-cn
        server wg-SNI 192.168.101.80:1444 send-proxy-v2-ssl-cn

frontend mc-front-HTTPS
        mode http
        option forwardfor
        bind 192.168.101.80:1443 ssl crt /etc/haproxy/isp.domain.net.pem accept-proxy
        http-request set-header X-Forwarded-Proto https
        default_backend mc-back-HTTPS

frontend wg-front-HTTPS
        mode http
        option forwardfor
        bind 192.168.101.80:1444 ssl crt /etc/haproxy/isp.domain.net.pem accept-proxy
        http-request set-header X-Forwarded-Proto https
        default_backend wg-back-HTTPS

backend mc-back-HTTPS
        mode http
        http-request add-header X-Forwarded-Host %[req.hdr(Host)]
        option http-server-close
        server mc-01 192.168.101.20:443 check port 443

backend wg-back-HTTPS
        mode http
        http-request set-header X-Forwarded-Host %[req.hdr(Host)]
        option http-server-close
        server wg-01 192.168.101.30:443 ssl check port 443

The firezone and haproxy instances are on the same RFC 1918 network (192.168.101.0/24), but just in case, the .env was edited to add the below (it made no difference).

EXTERNAL_TRUSTED_PROXIES=["192.168.53.101"]

Connections from outside hit HAProxy, which shows no HTTPS issues, and redirects from 80 to 443, but I’m a little lost on why the 503 is shown, is there any additional configuration required in caddy, or something else?

After much fun playing with HAProxy, I tried a diferent approach

The SNI front end stayed as is, but instead of going through a HAProxy front end/backend, went straight to the firezone instance

frontend sni-front
        bind 192.168.101.80:443
        mode tcp
        tcp-request inspect-delay 5s
        tcp-request content accept if { req_ssl_hello_type 1 }
        default_backend sni-back

backend sni-back
        mode tcp
        acl mc-sni req_ssl_sni -i meshcentral.domain.net
        acl wg-sni req_ssl_sni -i firezone.domain.net
        use-server mc-SNI if mc-sni
        use-server wg-SNI if wg-sni
        server mc-SNI 192.168.101.80:1443 send-proxy-v2-ssl-cn
        server wg 192.168.101.30:443

At which point, the connection works from outside, what I have yet to test is if this impacts LetsEncrypt…

tested working with letsencrypt on new deployment