Redirect a subdomain to backend server folder - haproxy

I have a wordpress installed on serverA 192.168.1.90/wordpress and a subdomain called mlb.example.com.
Using ACL in Haproxy, how do I redirect to a backend and still keep the subdomain name “mlb.example.com” rather than just showing the IP and folder in the browser.

Perhaps adding reqrep to the backend:
acl host_server hdr(host) -i mlb.example.com
use_backend wordpresswebsite if host_server
backend wordpresswebsite
reqrep ^([^\ :]*)\ /mlb.example.com/(.*) \1\ /wordpress/mlb/\2

Route by ACLs.
acl host_wordpresswebsite hdr(host) -i wordpresswebsite.acme.com
[...]
use_backend wordpresswebsite if host_wordpresswebsite
[...]
backend wordpresswebsite
[...]

Related

Redirect short/host name to subdomain

I have a collection of hosts that currently use just hostnames for reference, I'm switching over to using haproxy as an https proxy and would like to do a rewrite or redirect from http://server1/ to https://server1.internal.mydomain.com/.
# do a redirect for insecure connections
http-request redirect scheme https code 301 if !{ ssl_fc }
I have the HTTPS redirect/upgrade working as expected it's getting the rewrite/redirect configured properly that I'm hung up on, and I'm not really sure on the right verbiage to use when asking the question to get a relevant answer.
defaults
mode http
timeout client 10s
timeout connect 5s
timeout server 10s
timeout http-request 10s
frontend mydomain_frontend
# Listen for both http and https requests
bind *:80
bind *:443 ssl crt /etc/ssl/certs/Wildcard_mydomain_web_server.pem
# Setup conditional ACLs for hosts
acl server1_hosts hdr_beg(host) -i server1. server1 server1-2. server1-2
acl server2_hosts hdr_beg(host) -i server2. server2 server2-2. server2-2
# Setup Conditional ACLs for redirecting short/host names to FQDNs
acl is_internal hdr_sub(host) -i internal.mydomain.com
# I think the ACL is right, I'm just not sure how I would do the redirect, Is there string substitution?
http_request redirect location https://ORIGINALHOST.internal.mydomain.com if !is_internal
# do a redirect for insecure connections
http-request redirect scheme https code 301 if !{ ssl_fc }
use_backend server1_bend if server1_hosts
use_backend server2_bend if server2_hosts
default_backend server1_bend
# Setup DNS resolution
resolvers default
nameserver ns1 10.10.10.1:53
nameserver ns2 10.10.10.15:53
backend server1_bend
mode http
option forwardfor if-none
# server site 11.11.11.11:80 check resolvers default
server site server1.internal.mydomain.com:80 check resolvers default
backend server2_bend
mode http
option forwardfor if-none
# server site 10.10.10.10:80 check resolvers default
server site server2.internal.mydomain.com:80 check resolvers default
** EDIT **
I added an acl and a partial redirect statement to my example configuration, I think it is the beginning of what I am looking for but I don't know if it will work without string substitution in the redirect.
Updating the http-request line to use hdr(host) and pathq solved the issue for me.
http-request redirect location https://%[hdr(host)].internal.mydomain.com%[pathq] if !is_internal
hdr(host) - is the host from the URI minus the path and queries.
pathq - is the path including any queries. if we wanted just the path we could use just path.
The %[] pattern is important for triggering the substitution.

Haproxy acl - service unavailable

I'm trying to setup haproxy acl, and it gives me 503: Service unavailable error, even redirect by port works fine. What am I doing wrong?
Appreciate any help.
This doesn't work by x.x.x.x/havana :
frontend https
bind *:80
mode http
option httpclose
acl otter-path path -i /havana/
use_backend otter-server if otter-path
This shows backend fine by x.x.x.x:82 :
frontend otter-server
bind *:82
option forwardfor
default_backend otter-server
Backend configuration:
backend otter-server
server otter2 192.168.0.15:8004
acl otter-path path -i /havana/
remove the last "/" i.e:
acl otter-path path -i /havana
your trying to hitx.x.x.x/havana but matching x.x.x.x/havana/
the problem was - it redirects not to backend, but to backend/havana, which doesn't exist.
Solution is to remove subpath after redirect, so it points exact to backend root
backend annotrack-mouse
balance roundrobin
http-request set-uri %[url,regsub(^/havana/mouse,/,)] if { path_beg /ha$
server annotrack-mouse 192.168.0.10:3000
option httpchk

How can I redirect specific HTTPS request to a backend server using HAPROXY

I have a HTTPS server and want to redirect the specific request based on the URL to my Backend server.
Something like this should do it (for HTTP):
frontend http
bind *:80
acl mpd path_end -i .mpd
acl test hdr(host) test.com www.test.com
use_backend internal if test mpd
backend internal
http-request set-path /path/folder%[path]
# for older versions
# reqirep ^([^\ :]*)\ \/(.+\/)*(.*)\ \1\ /path/to/folder/\3
server internal-1 internal:80 check
Two ACLs in the frontend select the right backend and the http-request (reqirep for older versions) command overwrites the original request path.
You might need to tweak it.

HAProxy path_beg not redirecting

I'm testing a simple haproxy rule to make http://localhost/haproxy-dconv take me to http://cbonte.github.io/haproxy-dconv but it isn't working. 404 response seems to be from the site but the path isn't resolving.
frontend HTTP
mode http
bind *:80
acl url_dconv path_beg /haproxy-dconv
use_backend dconv-backend if url_dconv
backend dconv-backend
mode http
server dconv cbonte.github.io
Try this -
frontend HTTP
mode http
bind *:80
use_backend dconv-backend if { path_beg /haproxy-dconv/ }
backend dconv-backend
mode http
server dconv cbonte.github.io
Source: https://cbonte.github.io/haproxy-dconv/1.7/configuration.html#use_backend
That is because the Host header that is being sent is localhost, instead of cbonte.github.io. Add this to your backend:
http-request set-header Host cbonte.github.io
Also note that without the ending slash, you will get a 301, so make sure you send http://localhost/cbonte-dconv/ and fix your ACL.
You are using Haproxy in an incorrect way.
You need to match the ACL to get the URL between host and query parameter as you do:
acl url_dconv path_beg /haproxy-dconv
Then using this ACL to redirect from localhost if ACL is matched:
redirect prefix http://cbonte.github.io code 301 if url_dconv
But again this is more a conceptual problem of thinking redirect and matching path.

redirect all root domain request to www. subdomain, keeping the URL intact

I want to redirect all traffic to root domain to the www. version while still keeping path/query string intact, how can I do that? I have setup a HAproxy config like follows:
frontend http
bind *:80
bind *:443
acl has_www hdr_beg(host) -i www
http-request redirect code 301 location http://www.%[hdr(host)]%[req.uri] unless has_www
However this one does the following: example.com/abc?page=1 => www.example.com, where I actually wan't it to do: example.com/abc?page=1 => www.example.com/abc?page=1 - what am I missing?
if you are using HAProxy 1.5 and up this should work for you
Single domain :
acl has_www hdr_beg(host) -i www
redirect prefix http://www.example.com code 301 unless has_www
Multiple domains: (dirty but works)
# match non www requests:
acl has_www hdr_beg(host) -i www.
# add a header that says we need to redirect these type of requests (will explain later)
http-request add-header X-Host-Redirect yes unless has_www
# rule to identify newly added headers
acl www_redirect hdr_cnt(X-Host-Redirect) eq 1
# where the magic happens (insert www. in front of all marked requests)
reqirep ^Host:\ (.*)$ Host:\ www.\1 if www_redirect
# now hostname contains 'www.' so we can redirect to the same url
redirect scheme http if www_redirect
The reason why we add a new header is because it seems that in HAProxy 1.5 and up, acls are being evalutated on each reference. so when you try to do this without the new header it does this :
#catch all domains that begin with 'www.'
acl has_www hdr_beg(host) -i www.
#insert www. in front of all non www requests
reqirep ^Host:\ (.*)$ Host:\ www.\1 unless has_www
#now hostname contains 'www.' so when the next rule gets interpreted it does not match then fails
#redirect to new url
redirect code 301 prefix / if has_www
hope this helps. I've tested this with 5 different domains on HAProxy 1.5 and it worked fine and kept the query strings intact on redirect
A multi-domain solution for HAProxy 1.6 which redirects preserving the path and query parameters:
frontend 443
http-request redirect prefix https://www.%[hdr(host)] code 301 unless { hdr_beg(host) -i www. }