I want to configure simple redirect with HAproxy.
Desired behaviour: HAProxy receives request to example.com or https://example.com and returns https webserver start page from servers list excluding itself from a chain.
I tried with redirect location https://web1.com code 301 if example_acl
and it works for single server but I need 5 servers behind redirect, with web1.com, web2.com ... and round-robin. Maybe there is some specific config for backend section? please help
My current config is
-#------------------- GLOBAL SETTINGS ---------------------------
...
-#------------------- FRONTEND HTTP ---------------------------
frontend http_in
mode http
option httplog
bind *:80
stats enable
redirect scheme https if { hdr(Host) -i example.com }
-#------------------- FRONTEND TCP ---------------------------
frontend tcp_in
mode tcp
option tcplog
bind *:443
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
acl example_acl req.ssl_sni -i example.com
use_backend special_example if example_acl
-#------------------- Server Farms ---------------------------
backend special_example
mode tcp
balance roundrobin
?
I agree with the commenter, this seems like an unusual application, but nevertheless, HAProxy comes through.
I've created a hosts file entry on my test proxy so that example.com actually points to 127.0.0.1 so the tests, below, are actual responses from the proxy.
Let's say I want
example.com
to redirect to one of four servers,external-1.example.com
throughexternal-4.example.com
.This is a one-liner -- everything on one line, shown here as multiple lines for clarity.
This goes in the
frontend
section.{ req.hdr(host) -m str example.com }
is an anonmyous ACL that enables the redirectif
it matches the current request. Thelocation
is using therand(n)
sample fetch, which generates a random number between 0 and n-1; it's followed by (passes its value to) theadd(x)
converter, which adds x to the value -- in this case, we take possible values from 0 through (4 - 1) inclusive and add 1, so that the%[rand(4),add(1)]
expression evaluates to a number between 1 and 4 inclusive, which is implicitly cast to a string. We concatentatehttp://external-
with this integer, a dot, the incoming host header%[req.hdr(host)]
and the url%[url]
, which includes the path and query string.Test 1:
Test 2:
Yep, that's working.
If you needed to redirect to a set of hostnames that weren't sequentially numbered, the solution would be similar, but you'd use
http-request set-var
to store the random number in a transaction variable, then a series of redirect statements, one for each host, each of which with its own anonymous ACL that would evaluate the random value for equality to the integer matching that host, and redirect if the variable contained that value.The
rand()
fetch is not a random number generator of cryptographic quality, but certainly seems sufficient for this use case.