3

I have the following config, it's under the frontend section for tls connection and haproxy terminates https connections:

acl domain-acl-host hdr(host) -i domain.tld
rspadd X-Foo:\ bar if domain-acl-host
rspadd X-Baz:\ baz
http-response set-header X-Bar bar if domain-acl-host
use_backend backend_name if domain-acl-host

The use_backend directive works conditionally as expected (there are multiple different domain names served, and they are chosen correctly)

But headers are not added/set to the response conditionally.

I expect 3 extra headers to be added there: X-Foo, X-Baz, and X-Bar, but only X-Baz is added:

< HTTP/1.1 302 Found
< Server: nginx
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Cache-Control: max-age=0, must-revalidate, private
< Date: Sun, 14 Oct 2018 20:25:59 GMT
< Location: https://domain.tld/somewhere/else
< X-Baz: baz

I'm sure I'm missing something trivial, but reading documentation or google did not help.

PS: it's haproxy 1.8.8

zerkms
  • 431
  • 2
  • 5
  • 17

1 Answers1

3

there is no host header in the response headers, your acl never matches. use something like this:

    http-request set-var(txn.foo) req.hdr(host)
    http-response set-header bar 1 if { var(txn.foo) foo.bar }
txn.foo
  • 46
  • 1
  • 1
    I can confirm it works, but don't you think it's a bug? Isn't `acl` supposed to be set during request phase and survive til the end of transaction? It works fine with `sni`, while `sni` is only available during the tls handshake, long before request, yet it still is possible to match against it – zerkms Oct 14 '18 at 21:03
  • 1
    no it's working as intended. the acl is evaluated on responses because of your use of rspadd/http-response, and on responses, the hdr fetch can't find a host header. I would think sni is a different beast because it does not change with each request or response, headers do. – txn.foo Oct 14 '18 at 21:08
  • This answer is correct, but the further answer is no, ACLs do not work that way in HAProxy. ACLs are only evaluated at the point when they are tested, so in this case they would not be tested until during response processing... and the unqualified `hdr()` fetch assumes response header at that point... but if you qualify it as `req.hdr()` that does not change the expected behavior because the buffer holding request headers has already been released by then, so request fetches have nothing to search. The `txn` variables persist from request to response. – Michael - sqlbot Oct 15 '18 at 11:46