HAProxy dynamic server address based off of header value

haproxynetworkingPROXYreverse-proxy

Hello I'm attempting to route traffic back to a users machine in order to run a site locally but picking up the headers/cookies/routing logic for other origins that HAProxy supplies. Thus far though I have not been able to figure out how to do this. The documentation says that use of environment variables are usable https://cbonte.github.io/haproxy-dconv/configuration-1.5.html#4-server

Any part of the address string may reference any number of
environment variables by preceding their name with a dollar
sign ('$') and optionally enclosing them with braces ('{}'),
similarly to what is done in Bourne shell.

but I would imagine there is a way of using an acl or sample fetch but for the life of me I cannot figure out how to. Below is an example of one thing that I've tried. I have done a proof of concept by removing ${hdr(originalIp)} and using my IP but I want it to dynamically use the requesters IP if the cookie is present

### Sample config
acl has_local_cookie cook_sub(local) -i true
use_backend local    if has_local_cookie
backend local
server local-origin ${hdr(originalIp)}:443 ssl verify none

Best Answer

The problem with what you're trying is that it you're treating the entire configuration as though it were constantly being parsed and interpreted at runtime, which of course is not the case.

Certain arguments to the various directives are static, others dynamic, but server declarations are most definitely static. A server represents exactly one target address, not a different address per request.

You will need to configure a back-end for each developer, or you could put them all in one back-end, backend local with a single server declaration for each developer, server dev-1 192.168.1.1:80 ..., server dev-2 ..., etc.

Then use_backend local if { cook_sub(local) -i true }.

Then in the backend add a use-server to match the server names to the source IP use-server dev-1 if { src 192.168.1.1 } for each developer.

Note that { ... } is an anonymous ACL, a much cleaner (imho) way of testing simple conditions, particularly when the conditions are only evaluated in one place in the config. If you're testing the same condition in multiple places, named ACLs are better because they are only edited in one place, so you don't have to update them in multiple places like you would if you copy-pasted the same anonymous ACL around the config.

Related Topic