Haproxy redirection but keeping the URL same? - haproxy

I have a xml file under https://example.com/assets/content/foo.xml but I want it to access it as https://example.com/foo.xml. So outcome will be, the browser URL SHOULD BE = https://example.com/foo.xml but I will get the file context from https://example.com/assets/content/foo.xml location. How to set it in haproxy ?
I tried many solutions but none of them worked. here is what I tried and this would be completely wrong.
acl SEO_XML path_beg -i /foo.xml
http-request set-header X-Location-Path %[capture.req.uri] if SEO_XML
http-request replace-header X-Location-Path /foo.xml /assets/content/foo.xml if SEO_XML
http-request redirect location %[hdr(X-Location-Path)] if SEO_XML
use_backend shiba_dev_https if SEO_XML
I have also tried other solutions as follows :
reqrep ^([^\ :]*)\ /foo.xml/(.*) \1\ /assets/content/foo.xml/\2
http-request set-header Host example.com
http-request replace-path /foo.xml(.*) /assets/content/foo.xml\1
None of this worked as I have no clue how to do it. Any ideas pls ?
Haproxy Version = 1.8

Try this:
reqirep ^([^\ :]*)\ /foo.xml\ (.*) \1\ /assets/content/foo.xml\ \2 if { path_beg /foo.xml }

Related

HAProxy 2.5 http-request replace-path not working correctly

I need to have 301 redirect from example.com to www.example.com and from www.example.com/fr to www.example.com/fr/eshop
My haproxy.cfg:
global
log stdout format raw local0
defaults
log global
mode http
option dontlognull
option http-ignore-probes
log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"
option forwardfor
timeout connect 30s
timeout client 30s
timeout server 30s
frontend http
bind *:8080
# redirect to www
http-request redirect code 301 location https://www.example.com%[capture.req.uri] if { hdr(host) -i example.com }
### ACLs AND REDIRECTS ###
acl path_de path_beg /de
acl path_fr path_beg /fr
acl path_fr_eshop path_beg /fr/eshop
http-request replace-path /fr(.*) /fr/eshop\1 if path_fr !path_fr_eshop
use_backend de if path_de
use_backend fr if path_fr
default_backend de
backend de
http-request set-header Host www.example.com
server de-gw 91.X.X.X:443 check ssl verify none
backend fr
http-request set-header Host www.example.com
server fr-gw 10.X.X.X:80
With this config redirect from non-www to www works fine
This also works fine: www.example.com/fr is getting redirected to www.example.com/fr/eshop
but www.example.com/fr/ is getting redirected to www.example.comfr/eshop/fr
I tried with following below replace-path:
http-request replace-path ^/fr(/|$)(.*) /fr/eshop\1\2 if path_fr !path_fr_eshop
but it did not help behavior is the same, /fr/ is getting redirected to /fr/eshop/fr
Evetything works OK with following replace-path:
http-request replace-path /(.*) /fr/eshop if path_fr !path_fr_eshop

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 routes requests to wrong server

We are using HAProxy for our app. We have a separate server for site, API, docs and blog.
We have following HAproxy configurations
frontend http
mode http
bind *:80
redirect prefix https://www.kbook.com code 301 if { hdr(host) -i kbook.com }
redirect scheme https code 301 if { hdr(host) -i www.kbook.com } !{ ssl_fc }
redirect scheme https code 301 if { hdr(host) -i docs.kbook.com } !{ ssl_fc }
redirect scheme https code 301 if { hdr(host) -i api.kbook.com } !{ ssl_fc }
acl www hdr(host) -i www.kbook.com
acl docs hdr(host) -i docs.kbook.com
acl api hdr(host) -i api.kbook.com
acl blog path -i -m beg /blog
use_backend blog_server if www blog
use_backend site_server if www
use_backend api_server if api
use_backend docs_server if docs
frontend https
mode http
bind *:443 ssl crt /etc/ssl/live/wildcard_kbook.pem alpn h2,http/1.1
redirect prefix https://www.kbook.com code 301 if { hdr(host) -i kbook.com }
use_backend blog_server if { ssl_fc_sni -i www.kbook.com } { path -i -m beg /blog }
use_backend site_server if { ssl_fc_sni -i www.kbook.com }
use_backend api_server if { ssl_fc_sni -i api.kbook.com }
use_backend docs_server if { ssl_fc_sni -i docs.kbook.com }
HAProxy Version: 2.2.0-1ppa1~bionic
Issue:
When we access the site (www.kbook.com), it works sometimes. Sometimes it goes to blog server, says 404 not found. I expect "www.kbook.com" should always go to the site server.
This happens even to docs and API requests. Those requests are also going to the blog server sometimes.
HAproxy directs the requests to the wrong server. Why does it happen? is there any issue with configurations?
This was a bug in 2.2.0 and it should be fixed in 2.2.1

Dynamic server name and header in HAProxy

I’m looking for the equivalent of this backend code block below for requests to www.example.com and example.com.
http-response set-header X-Target example.com
server web-servers site.example.com:80 check
I take all the requests to www.example.com but I want to serve them to site.example.com using haproxy. There are several variations of example.com so I would like to have a list of allowed domains and then if they're allowed I would like to have a backend code block like below where I could use %[req.hdr(Host)] as the value in the http-response X-Target statement.
http-response set-header X-Target %[req.hdr(Host)]
server web-servers site.%[req.hdr(Host),regsub(^www.,,)]:80 check
HA-Proxy version 2.1.4-273103-54 2020/05/07 - https://haproxy.org/
I’m getting this error when I try haproxy -c -f haproxy.test
[root#pm-prod-haproxy05 haproxy]# haproxy -c -f haproxy.test
[ALERT] 259/180932 (16116) : parsing [haproxy.test:40]: ‘http-response set-header’: sample fetch may not be reliably used here because it needs ‘HTTP request headers’ which is not available here.
[ALERT] 259/180932 (16116) : Error(s) found in configuration file : haproxy.test
[root#pm-prod-haproxy05 haproxy]#
I've also tried this:
http-request set-header X-Target %[req.hdr(Host)]
http-request set-header X-Hostname %[req.hdr(Host),regsub(^www.,site.,)]
http-request web-server do-lookup(hdr(X-Hostname))
server web-servers web-server:80 check
This is my full configuration.
global
log 127.0.0.1 local2 debug
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
daemon
stats socket /var/lib/haproxy/stats
defaults
mode http
option httplog
log global
option dontlognull
option http-server-close
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
frontend frontend-http
bind *:80
bind *:443
acl redirect path_beg -i /rd
use_backend backend-tracking if redirect
default_backend backend-default
backend backend-default
option forwardfor
http-response set-header X-Publishing-system website
http-response set-header X-Target %[req.hdr(Host)]
server web-servers site.%[req.hdr(Host),regsub(^www.,,)]:80 check
backend backend-tracking
option forwardfor
http-response set-header X-Publishing-system redirect
http-request set-uri %[url,regsub(^/rd,/,)]
server web-hp www.trackingplatform.com:80 check
About Header manipulation
As the ALERT message say you can't use request header in the response. You should replace the following line.
Wrong line
http-response set-header X-Target %[req.hdr(Host)]
Right Line
http-request set-header X-Target %[req.hdr(Host)]
The Backend-Server should not remove this header. If you not want to send the Backend-Server the 'X-Target' host header then can you use a session variable to save the host header from the request to the response phase.
http-request set-var(txn.my_host) req.hdr(host),lower
http-response set-header X-Target %[var(txn.my_host)]
In the documentation are the set-var and set-header directive quite good explained.
http://cbonte.github.io/haproxy-dconv/1.8/configuration.html#4-http-request
About the server manipulation
This line could not work because haproxy tries to resolve the target server at start time.
server web-servers site.%[req.hdr(Host),regsub(^www.,,)]:80 check
In newer version of haproxy. like 2.1, can you dynamically resolve and set the destination hosts.
http://cbonte.github.io/haproxy-dconv/2.1/configuration.html#4.2-http-request%20do-resolve
I assume you want to change the host header for the target server that the right virtual server is used.
My suggestion to solve your issue is to change the host header and set the server name to a resolvable address.
backend backend-default
option forwardfor
http-response set-header X-Publishing-system website
http-request set-header X-Target %[req.hdr(Host)]
http-request replace-header Host ^www(.*) site.\1
http-request set-header X-NewTarget %[req.hdr(Host),regsub(^www.,,)]
server web-servers site.example.com:80 check
This backend config is only syntax checked.
About dynamic backend server
The server should be resolved dynamically.
For that solution is at least HAProxy 2.0 necessary.
I copy here some parts of the doc http-request do-resolve for this answer.
You will need to add a section resolvers to your config
resolvers mydns
# use here your prefered DNS Servers
nameserver local 127.0.0.53:53
nameserver google 8.8.8.8:53
timeout retry 1s
hold valid 10s
hold nx 3s
hold other 3s
hold obsolete 0s
accepted_payload_size 8192
frontend frontend-http
bind *:80
bind *:443
# define capture buffer for backend
declare capture request len 60
acl redirect path_beg -i /rd
use_backend backend-tracking if redirect
default_backend backend-default
# ... some more backends
backend backend-default
option forwardfor
http-response set-header X-Publishing-system website
http-request set-header X-Target %[req.hdr(Host)]
# replace www with site in host header
http-request replace-header Host ^www(.*) site.\1
# if necessary set X-NewTarget header
http-request set-header X-NewTarget %[req.hdr(Host),regsub(^www.,,)]
# do dynamic host resolving for dynamic
# server destination for
# the replaced Host Header above
http-request do-resolve(txn.myip,mydns,ipv4) hdr(Host),lower
# print the resolved IP in the log
http-request capture var(txn.myip) id 0
# rule to prevent HAProxy from reconnecting to services
# on the local network (forged DNS name used to scan the network)
# add the IP Range for the destination host here
http-request deny if { var(txn.myip) -m ip 127.0.0.0/8 10.0.0.0/8 }
http-request set-dst var(txn.myip)
server clear 0.0.0.0:0
Please take care about the note in the documentation
NOTE: Don't forget to set the "protection" rules to ensure HAProxy won't be used to scan the network or worst won't loop over itself...

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