haproxy nested conditions for acl - haproxy

I need nested ACL conditions
acl route1 hdr_sub(host) -i abc.com hdr_sub(host) -i xyz.com
acl route2 path_beg /m1
acl route3 path_beg /m2
use backend back1 if route1 (route2 or route3)
// essentially
route1 AND (route2 OR route3)
to match backends. What would be the correct HA code equivalent to this ?

Rules in a single ACL are ORed, so, you can combine the route2 and route3 rules with this:
acl route2 path_beg /m1
acl route2 path_beg /m2
use backend back1 if route1 route2
Conditions also support the || operator, but not parenthetical grouping for precedence, so a b || c means (a and b) or (c), which isn't equivalent to what you want... so if you don't want to combine the ACLs as shown above, you would need this...
use backend back1 if route1 route2 || route1 route3
...which is not exactly intuitive.
Or this:
use backend back1 if route1 route2
use backend back1 if route1 route3

See HA manual Section 7.2. Using ACLs to form conditions
You can declare an ACL to group those two conditions :
acl route2_or_route3 path_beg /m1 /m2
And use it in your rule:
use backend back1 if route1 route2_or_route3
Which means route1 and (route2 or route3).
Conditions in an ACL are grouped by an implicit logical OR.
Conditions in an action rule are grouped by an implicit logical AND.

Related

How haproxy uses sni to spread traffic?

My configuration is as follows, currently the web site works fine, I also have a public ip with an ssl certificate, it doesn't work,It is routed to the web site when requested, is there any way to fix it? Thanks
acl is_a01 ssl_fc_sni -i test.xyz
acl is_a02 ssl_fc_sni -i 12.13.14.16
use_backend n1 if is_a01
use_backend n2 if is_a02
default_backend web
There is a quite good description on this blog post Enhanced SSL Load Balancing with Server Name Indication (SNI) TLS Extension.
In the documentation is this the keyword you are searching for req.ssl_sni
Here is a untested snipplet from your question
# Wait for a client hello for at most 5 seconds
tcp-request inspect-delay 5s
# optionaly check if it's ssl_hello_type 1
tcp-request content accept if { req.ssl_hello_type 1 }
# The test values (test.xyz,12.13.14.16) *MUST*
# be in the certificate
acl is_a01 req.ssl_sni -i test.xyz
acl is_a02 req.ssl_sni -i 12.13.14.16
use_backend n1 if is_a01
use_backend n2 if is_a02
default_backend web

Haproxy URL redirect

Using haproxy 2.0.13-2
Having an issue with ACL's and redirect
I want to ACL on stuff.xyz.com/mycrap.aspx and redirect that to junk.abc.com
As a test I have an
ACL acl_stuff hdr(host) -i stuff.xyz.com/junk.aspx
use_backend be_stuff if acl_stuff
backend be_stuff
stats enable
option forwardfor
http-response add-header X-Backend ohs1docker01
server ohs1docker01 ohs1docker01.def.com:80 check
However even the ACL with the backend isnt working. I hit that page and I get a 404 which leads me to believe the ACL is not getting hit so the traffic is not getting to the backend.
Im hoping someone can give me some direction on this
Looks like you want to use http-response redirect
http-response redirect code 301 location https://www.junk.abc.com if { hdr_beg(host) -i stuff.xyz.com }
The acl acl_stuff hdr(host) -i stuff.xyz.com/junk.aspx can't match because there is a mix of host and path.
To match host and path try this.
acl match_path path_beg /junk.aspx
acl match_host hdr_beg(host) -i stuff.xyz.com
http-response redirect code 301 location https://www.junk.abc.com if match_host match_path

haproxy redirect to new domain if string found in request but keep and send all URL parameters

I want to do the following using haproxy:
if I get a request on domain 1 which includes a certain string (ie map1), I want to keep all that is after first / following the domain and redirect it all to domain 2. For example:
If I get https://sub1.domain1.gr/kjhkjhkh??efreerwer
I want to redirect to
https://sub2.domain2.gr/kjhkjhkh??efreerwer
Trying the following:
acl domain1_url hdr(host) sub1.domain1.gr
acl map1_uri capture.req.uri -m reg map1
http-request set-var(req.map1_uri) if domain1_url map1_uri
http-request set-path /%[var(req.map1_uri)]%[path] if { var(req.map1_uri) -m found }
http-request set-header Host sub2.domain2.gr if { var(req.map1_uri) -m found }
Is there something wrong with this logic?
Thank you in advance!
Well, I solved the problem.
I used:
acl domain1_url hdr(host) sub1.domain1.gr
acl map1_uri capture.req.uri -m reg map1
http-request redirect code 301 location http://sub2.domain2.gr%[capture.req.uri] if map1_uri
Read about it at http://patg.net/haproxy,apache/2017/08/04/haproxy/

HAProxy: hdr_dom(host) with redirects

We have a couple of haproxy configurations running fine for the most part.
In our scenario, we simply route requests based on domain names.
Here a sample for one domain, drawmessage.com:
frontend http
bind *:80
redirect prefix http://app.drawmessage.com code 301 if { hdr_dom(host) -i www.app.drawmessage.com }
redirect prefix http://drawmessage.com code 301 if { hdr_dom(host) -i www.drawmessage.com }
redirect prefix https://drawmessage.com code 301 if { hdr_dom(host) -i drawmessage.com }
use_backend http:app.drawmessage.com if { hdr_dom(host) -i app.drawmessage.com }
use_backend http:app.drawmessage.com if { hdr_dom(host) -i app-drawmessage-com.d250.hu }
use_backend http:drawmessage.com if { hdr_dom(host) -i drawmessage.com }
use_backend http:drawmessage.com if { hdr_dom(host) -i drawmessage-com.d250.hu }
There are other domains also, this is filtered for this domain only. As you can see, after redirects for www, we apply a special redirect for drawmessage.com, but theoretically not for app.drawmessage.com.
frontend https
bind *:443 ssl crt /var/haproxy
redirect prefix https://app.drawmessage.com code 301 if { hdr_dom(host) -i www.app.drawmessage.com }
redirect prefix https://drawmessage.com code 301 if { hdr_dom(host) -i www.drawmessage.com }
use_backend https:app.drawmessage.com if { hdr_dom(host) -i app.drawmessage.com }
use_backend https:app.drawmessage.com if { hdr_dom(host) -i app-drawmessage-com.d250.hu }
use_backend https:drawmessage.com if { hdr_dom(host) -i drawmessage.com }
use_backend https:drawmessage.com if { hdr_dom(host) -i drawmessage-com.d250.hu }
The problem is that actually, we do not want a redirect to https for the subdomain app.drawmessage.com, but since we have a redirect for the domain the redirect rule applies for both. Reordering the rules in a way, so that the sorting matches the configuration we want to achieve does produce the same result, and we get haproxy warnings:
a 'redirect' rule placed after a 'use_backend' rule will still be processed before.
If the order of configuration lines affects the order of processing a request, thus the ordering is a configuration parameter itself, why are redirect rules processed before use_backend rules? ...
Anyone has a suggestion how to achieve domain-based routing, with the correct preference of redirects? I would prefer a clean and simple way, ..
Don't use hdr_dom(). Just use hdr().
redirect prefix https://drawmessage.com code 301 if { hdr(host) -i drawmessage.com }
The _dom suffix means you want to match the value given later against any number of complete, consecutive domain-name-like tokens found in the specified header, so the pattern you provide must begin either at the beginning of the string or immediately following a . and must end either at the end of the string or be immediately followed by a .. That isn't what you want to do, so hdr_dom() isn't the correct fetch to use.
The notation may imply that you are comparing left value against right value, but the comparison is actually right value against left value.
a 'redirect' rule placed after a 'use_backend' rule will still be processed before because these directives are handled by different parts of the HAProxy code, at different stages of request processing. Within each class of rule, the order is preserved, but redirects are handled near the beginning and backend selection is near the end of request processing.

Redirecting URL using HAProxy

Im trying to direct the following URL https://register.company.xzy to https://register.company.xzy/register/supplier?code=
My haproxy config has acls in it for some existing subdomains and has been working well but i cant see to get this to work:
frontend https
bind 10.10.2.150:443 ssl crt /etc/apache2/ssl/star.company.xyz.pem
mode http
option httpclose
option forwardfor
reqadd X-Forwarded-Proto:\ https
acl www.company.xyz hdr(host) -i www.company.xyz
acl portal.company.xyz hdr(host) -i portal.company.xyz
acl live.company.xyz hdr(host) -i live.company.xyz
acl register.company.xyz hdr(host) -i register.company.xyz
use_backend website_live_servers if www.company.xyz
use_backend website_live_servers if portal.company.xyz
use_backend application_live_servers if live.company.xyz
use_backend register_live_servers if register.company.xyz
backend application_live_servers
mode http
cookie SERVERID insert indirect nocache
server server1 server1.company.xyz:80 check cookie $1
backend register_live_servers
mode http
cookie SERVERID insert indirect nocache
server server2 server2.company.xyz:80 check cookie $1
backend website_live_servers
mode http
cookie SERVERID insert indirect nocache
server server3 server3.company.xyz:80 check cookie $1
server server3 server3.company.xyz:80 check cookie $2
Any ideas or guidance?
Well what you need is to rewrite URL
http-request set-path <fmt> [<condition>]
http-request set-query <fmt> [<condition>]
OR rewrite complete URI
http-request set-uri <fmt> [<condition>]
rewriting url path