Configuration working with curl but not with a browser

I have a simple haproxy configuration that looks like the following:

    # configure logging
    log stdout format raw local0 debug

    # set default parameters to the modern configuration
    tune.ssl.default-dh-param 2048
    ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
    ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets

    mode    http
    option  forwardfor
    option  http-server-close

    stats   enable
    stats   uri /hastats
    stats   realm HAproxy\ Stats
    stats   auth *****:*****

    timeout client 30s
    timeout connect 4s
    timeout server 30s

frontend ft
    mode http
    option httpslog
    option logasap
    log global
    bind    :443 ssl crt /etc/certs
    bind    :80
    redirect scheme https code 301 if !{ ssl_fc }
    # HSTS (15768000 seconds = 6 months)
    http-response set-header Strict-Transport-Security max-age=15768000

    acl host_op_domain_com hdr(host) -i beg
    use_backend k8s_cluster_prod if host_op_domain_com

backend k8s_cluster_prod
    mode http
    option forwardfor
    http-send-name-header Host
    server node1 check ssl verify none
    server node2 check ssl verify none
    server node3 check ssl verify none
    server node4 check ssl verify none
    server node5 check ssl verify none

For testing purposes, I am running haproxy locally with docker listening on port 8443.
There, I updated my /etc/hosts file with the following line:

It (kind of) works when I try to access the website with curl: curl -H "" --insecure The nginx backend service is answering (even though the host header gets stripped - but it is a different problem).

The haproxy log looks like: [19/Jan/2024:16:32:12.647] ft~ k8s_cluster_prod/ 0/0/172/44/+216 404 +299 - - ---- 1/1/1/0/0 0/0 "GET HTTP/2.0" 0/0000000000000000/0/0/0 -/TLSv1.3/TLS_AES_256_GCM_SHA384

However, it does not throw the same error when I try to open the url in a browser (here Firefox). It returns a 503 error: No server is available to handle this request.

The haproxy error log contains: [19/Jan/2024:16:38:11.575] ft~ ft/<NOSRV> -1/-1/-1/-1/+0 503 +217 - - SC-- 1/1/0/0/0 0/0 "GET HTTP/2.0" 0/0000000000000000/0/0/0

It seems that the acl does not work as intended… but I can’t figure out why

Does anyone have an idea?

A browser would add the port number to the Host header (in cases where a non standard port is used) making your ACL not match anymore.

I would suggest a different method to reproduce the issue with curl:

curl --insecure --resolve

So instead of manually constructing the Host header (which in this case hid the problem from you), you are telling curl to overwrite DNS as per the --resolve directive.

I think curl would then behave the same, but I suggest you check by the headers by running it in verbose mode (-vv).

1 Like

Thanks for the quick reply!

You are right! I can reproduce the same behaviour with your curl command:

curl -vv --insecure --resolve

leads to the following log: [19/Jan/2024:17:25:40.384] ft~ ft/<NOSRV> -1/-1/-1/-1/+0 503 +217 - - SC-- 1/1/0/0/0 0/0 "GET HTTP/2.0" 0/0000000000000000/0/0/0

I’m now left with the question about the host header being stripped from the request to the backend server.

You are overwriting the Host header unconditionally in the backend:

http-send-name-header Host

I know. I’ll need to debug it further. But this is off-topic.
Thanks for your help!