HAProxy redirect to subdomain - redirect

I am trying to redirect these:
http://www.example.co.uk/blog/xyz?a=b
https://www.example.co.uk/blog/xyz?a=b
to these:
http://blog.example.co.uk/xyz?a=b
https://blog.example.co.uk/xyz?a=b
But struggling with the documentation and the best way to do this.
* Update *
This is what I have got working at the moment. If I pass in:
http://www.example.co.uk/blog?a=b
then this redirects to:
http://blog.example.co.uk?a=b
... and the section of the config:
acl blog_page path_beg -i /blog
use_backend blog_site if blog_page
backend blog_site
reqrep ^([^\ :]*)\ \/?(.*)\/blog\/?(.*) \1\ /\2\3
redirect prefix http://blog.example.co.uk code 301

The following line in the frontend section will accomplish this rewrite and redirect.
Shown as multiple lines for clarity, this must all appear on a single line of your configuration:
http-request redirect
code 301
location https://blog.example.com%[capture.req.uri,regsub(^/blog,)]
if { hdr(host) -i www.example.com } { path_beg /blog }
If the host header matches www.example.com and path begins with blog, redirect to a location beginning with the literal string https://blog.example.com then concatenate a value derived by taking the request URI (path + query string) and using regex substitution to remove /blog from the beginning.
Verifying:
$ curl -v 'http://www.example.com/blog/posts?which=this&that=1'
* Hostname was NOT found in DNS cache
* Trying 127.0.0.1...
* Connected to www.example.com (127.0.0.1) port 80 (#0)
> GET /blog/posts?which=this&that=1 HTTP/1.1
> User-Agent: curl/7.35.0
> Host: www.example.com
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Content-length: 0
< Location: https://blog.example.com/posts?which=this&that=1
The redirect location appears to be correct.
If you want to redirect http and https separately, you'd need two lines, each of them testing an additional condition to determine whether the original request was over http or https.
Using the regsub() converter requires HAProxy 1.6+.

Related

Haproxy redirect and fowarding the subdomain

I have an Haproxy server and I need when the user type any_word.registro.myserver.com.br on the browser, the Haproxy redirect to https://app2.otherserver.com.br/register/**any_word**
The any_word is a captcha (*.registro.myserver.com.br)
Today I have the following redirect that doesn't forward:
acl fqdn_register_all hdr_dom(host) -i registro.myserver.com.br
redirect prefix https://app2.otherserver.com.br/register code 302 if fqdn_register_all
How should i change the above code?
Best regards
this rule should do the work:
acl fqdn_register hdr_dom(host) -i registro.myserver.com.br
capture request header Host len 128
redirect prefix https://app2.otherserver.com.br/register/%[capture.req.hdr(0)] code 302 if fqdn_register
hope it helps.

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

How to redirect to domain name with https using haproxy

I tried to receive request and want to redirect it to other host using dns name and exposed with https protocol. For example, my server is http://8.8.8.8:10101/partnerA/getUser. I want haproxy redirect this to https://partner.com/partnerA/getUser (same path as the source).
I also want to filter by path for another redirect destination such as http://8.8.8.8:10101/partnerB/getMarketShare will redirected by HAProxy to https://subdomainb.differentpartner.com/partnerB/getMarketShare(notice the path also follow the same rule, but based on path it will give different host name.
I tried below haproxy.cfg
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend main
bind *:10101
acl url_partnerA path_beg -i /partnerA
acl url_partnerB path_beg -i /partnerB
http-request redirect scheme https if url_partnerA
http-request redirect scheme https if url_partnerB
http-request redirect prefix https://partnerA.com if url_partnerA
http-request redirect prefix https://subdomainb.differentpartner.com/ if url_partnerA
default_backend app
#---------------------------------------------------------------------
# round robin balancing between the various backends
backend app
balance roundrobin
# server app1 127.0.0.1:11003 check
But everytime I access (I use http) POST http://8.8.8.8:10101/partnerA/getUser, the log from haproxy -f haproxy10101.cfg -d will give me this
00000000:main.accept(0005)=0009 from [8.8.8.8:48554] ALPN=<none>
00000000:main.clireq[0009:ffffffff]: POST /partnerA/getUser HTTP/1.1
00000000:main.clihdr[0009:ffffffff]: Host: 8.8.8.8:10101
00000000:main.clihdr[0009:ffffffff]: User-Agent: curl/7.47.0
00000000:main.clihdr[0009:ffffffff]: Accept: */*
00000000:main.clihdr[0009:ffffffff]: Authorization: Basic dGNhc2g6RzBqM2tmMHJsMWYzIQ==
00000000:main.clihdr[0009:ffffffff]: Content-Type: application/json
00000000:main.clihdr[0009:ffffffff]: Postman-Token: 45a236c-740a-4859-a13a-1c45195a99f2
00000000:main.clihdr[0009:ffffffff]: cache-control: no-cache
00000000:main.clihdr[0009:ffffffff]: Content-Length: 218
00000000:main.clicls[0009:ffffffff]
00000000:main.closed[0009:ffffffff]
Anything I miss to make it work? Thanks

404 redirect to another server/domain

I'm looking for a solution with redirects to another domain if the response from HTTP server was 404.
acl not_found status 404
acl found_ceph status 200
use_backend minio_s3 rsprep ^HTTP/1.1\ 404\ (.*)$ HTTP/1.1\ 302\ Found\nLocation:\ / if not_found
use_backend ceph if found_ceph
But still not working, this rule goes to minio_s3 backend.
Thank you for you advice.
When the response from this backend has status 404, first add a Location header that will send the browser to example.com with the original URI intact, then set the status code to 302 so the browser executes a redirect.
backend my-backend
mode http
server my-server 203.0.113.113:80 check inter 60000 rise 1 fall 2
http-response set-header Location http://example.com%[capture.req.uri] if { status eq 404 }
http-response set-status 302 if { status eq 404 }
Test:
$ curl -v http://example.org/pics/funny/cat.jpg
* Hostname was NOT found in DNS cache
* Trying 127.0.0.1...
* Connected to example.org (127.0.0.1) port 80 (#0)
> GET /pics/funny/cat.jpg HTTP/1.1
> User-Agent: curl/7.35.0
> Host: example.org
> Accept: */*
The actual back-end returns 404, but we don't see it. Instead...
< HTTP/1.1 302 Moved Temporarily
< Last-Modified: Thu, 04 Aug 2016 16:59:51 GMT
< Content-Type: text/html
< Content-Length: 332
< Date: Sat, 07 Oct 2017 00:03:22 GMT
< Location: http://example.com/pics/funny/cat.jpg
The response body from the back-end's 404 error page will still be sent to the browser, but -- as it turns out -- the browser will not display it, so no harm done. This requires HAProxy 1.6 or later.
#Michael's answer is rather good, but isno't working for me for two reasons:
Mainly because the %[capture.req.uri] tag resolves to empty (HA Proxy 1.7.9 Docker image)
Also due to the fact that the original assumptions are incomplete, due to the fact that the frontend section is missing...
So I struggled for a while, as you find all kinds of answers on the Internet, between those guys who swear the 404 logic should be put in the frontend, vs those who choose the backend, and any possible kind of tags...
This is my answer, which works for me.
My use case is that if an image is not found on the backend behind HA Proxy, then an S3 bucket is checked.
The entry point is: https://myhostname:8080/path/to/image.jpeg
defaults
mode http
global
log 127.0.0.1:514 local0 debug
frontend come_on_over_here
bind :8080
# The following two lines are here to save values while we have access to them. They won't be available in the backend section.
http-request set-var(txn.path) path
http-request set-var(txn.query) query
http-request replace-value Host localhost:8080 dev.local:80
default_backend onprems_or_s3_be
backend onprems_or_s3_be
log global
acl path_photos var(txn.path) -m beg /path/prefix/i/want/to/strip/off
acl p_ext_jpeg var(txn.path) -m end .jpeg
acl is404 status eq 404
http-response set-header Location https://mybucket.s3.eu-west-3.amazonaws.com"%[var(txn.path),regsub(^/path_prefix_i_want_to_strip_off/,/)]?%[var(txn.query)]" if path_photos p_ext_jpeg is404
http-response set-status 301 if is404
server onprems_server dev.local:80 check

haproxy redirect both scheme and location together

I need to redirect a specific http URL first to its equivalent https and then on to a completely different https URL (don't ask why I can't just redirect the original http straight to the final https URL, this is what the client wants and the client is always right!). Additionally I need to be able to redirect the original https to the different https too.
So, what I need is the ability to redirect http://foo.bar.com => https://foo.bar.com and then https://foo.bar.com => https://another.foobar.com, as well as redirecting https://foo.bar.com => https://another.foobar.com.
Currently to redirect just https://foo.bar.com => https://another.foobar.com I'm using this:
acl is_new_portal hdr(host) -i foo.bar.com
redirect location https://another.foobar.com code 302 if is_new_portal
with an initial bind on port 443, and I know to redirect http to https I would use:
redirect scheme https code 302 if !{ ssl_fc }
(using code 302 rather than 301 as eventually another.foobar.com will be removed, so I don't want the redirection permanently cached in clients' browsers)
but I need to be able to do both relocations, and I'm not sure how you combine the two?
I am not certain to understand if your issue is related to the binding or to the ACLs. You already have all the answers to your question. You can wrap them in a simple frontend:
frontend main
bind :80
bind :443 ssl crt yourCertFile
acl is_new_portal hdr(host) -i foo.bar.com
redirect scheme https code 302 if !{ ssl_fc } is_new_portal
redirect location https://another.foobar.com code 302 if { ssl_fc } is_new_portal
http-response set-header Strict-Transport-Security max-age=31536000;\ includeSubDomains;\ preload; if { ssl_fc }
The space between ACLs after the if is interpreted as a AND. So you will get something like:
redirect to https IF the host is foo.bar.com AND NOT using ssl
redirect to https://another.foobar.com IF the host is foo.bar.com AND using ssl