HAproxy - How to forward traffic to backend by a matching header? - header

E.g. the header contains: X-DEMO-HOST-VERSION: test - how do i need to setup the haproxy config to forward to a specific backend? Can this be done within the backend or in the frontend?
Regarding to the documentation i'm a little bit confused.

You need a check header (hdr in haproxy) value via ACL. Try it:
frontend header_front
bind *:80
mode http
option forwardfor if-none
acl demo_host_version hdr(X-DEMO-HOST-VERSION) -i test
use_backend test_backend if demo_host_version
default_backend prod_backend
backend test_backend
...
backend prod_backend
...
Test for you header:
acl demo_host_version hdr(X-DEMO-HOST-VERSION) -i test
use_backend test_backend if demo_host_version
The logic:
IF X-DEMO-HOST-VERSION=test use test_backend ELSE use prod_backend
UPD:
If u need acl for path in URL (example.com/test/):
acl demo_host_path path_beg /test/
use_backend test_backend if demo_host_path
If u need use a two ACL in if statement use it:
acl demo_host_version hdr(X-DEMO-HOST-VERSION) -i test
acl demo_host_path path_beg /test/
use_backend test_backend if demo_host_path demo_host_version
UPD for check URL:
Subdomain check. If u domain test.example.com or test.abc.com, try it:
acl host_sub_domain hdr_beg(host) -i test
For full domain check, eg test.example.com, try it:
acl host_full_domain hdr(host) -i test.example.com

Related

How to disable direct port access through URL

So I was wondering if it's possible to block direct port access via URL. I set up my own security system with a raspberry pi and made a web page to where I can view my livestream. It uses port 8081 for stream viewing, but if I type in www.mydomain.com:8081 it just bypasses my website and goes directly to the stream. I would like to disable that. (in the future I will require username and password to access the stream). Is this possible at all? Or even if I have to redirect it to my home page that will be fine also. I've tried searching and everything is showing up as virtualhost which I don't think is what I'm looking for.
I am using apache as my webserver and motion for my surveillance system. I also have port 80 and 8081 forwarded
If you want to block direct access, you just have to block it through the system ( and configure Apache/Nginx to do a proxypass to the port)
Example for you:
On the terminal run the following commands so you won't be able to directly access it (but your Apache/Nginx will be able to redirect you here)
#First make the port accessible locally
iptables -A INPUT -p tcp --dport 8081 -s 127.0.0.0/8 -j ACCEPT
#Now drop request from all other sources
iptables -A INPUT -p tcp --dport 8081 -j DROP
On the Config, for Nginx would be something like this:
location /security {
expires max;
proxy_pass http://127.0.0.1:8081;
auth_basic "Restricted"; # If you want Basic Auth
auth_basic_user_file /etc/nginx/.htpasswd; # If you want Basic Auth
}
Now you just go to www.mydomain.com/security and will have login prompted (if you use the Basic Auth), otherwise you'll get the Livestream.

HAProxy http passtrough proxy instead of 304 redirect

I am trying to get the equivalent of the nginx passtrough where a user would see my website url in the address bar but get all the content to be proxied from another website.
At the moment the code below redirects the user to example2 by returning a 304, instead of proxying the traffic.
I need it to work with http (not tcp) because I need this as part of an AB test where I need to inspect the cookies. Please check the comments on the code below for what I am trying to do.
defaults
mode http
log global
option httplog
log 127.0.0.1 local0
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
listen http
bind 127.0.0.1:8080
acl set_cookie path_beg /set-cookie
use_backend b-backend if { req.cook(SITEID) -m beg b-backend }
use_backend b-backend if set_cookie
default_backend ab-split-backend
backend a-backend
option forwardfor
server example1 example1.com:443 check maxconn 3000 inter 30s
backend b-backend
cookie SITEID insert
option http_proxy
# how do I get example2 to passtrough and not 304 redirect?
server example2 example2.com:443 check maxconn 3000 inter 30s
backend ab-split-backend
balance roundrobin
cookie SITEID insert indirect nocache maxlife 48h
# how do I get example2 to passtrough?
server example2 example2.com:443 weight 50 cookie b-backend
server example1 example1.com:443 weight 50 cookie a-backend
HTTP 304 is not really a redirect, it is an empty response indicating Not Modified which tells the client that the server would have responded with a 200 and served the content, but the requested asset has not changed, so the client can just use what it has cached.
So I'm not entirely sure what you're seeing is incorrect behavior. That is, your requests may be being passed through just fine, and the backend server may be correctly responding with a 304.
The server makes the decision to respond with this code based on information provided in the request headers If-Modified-Since and/or If-None-Match. So if you really want to disable this caching mechanism and ensure a complete 200 response every time, you can instruct HAProxy to delete these headers from the incoming request:
listen http
bind 127.0.0.1:8080
acl set_cookie path_beg /set-cookie
# Delete headers related to caching
http-request del-header If-Modified-Since
http-request del-header If-None-Match
use_backend b-backend if { req.cook(SITEID) -m beg b-backend }
use_backend b-backend if set_cookie
default_backend ab-split-backend
it looks like what you are trying to do is keep your system from trying to pass it through via SSL and instead do clear text based assessments for testing purposes. I would recommend seeing a snippet from my config below on http-request redirects and also look into HAProxy schemes. I would also recommend seeing the additional example for instance based redirection, specifically for a dictated location, that way you dont unencrypt traffic accidentally that you want to remain encrypted.
As for the information proxied from another location, your best bet for that would be with using Cloudflare, especially if you are looking for some form of DDoS/additional layers of security. The alternative is building your own custom anti-DDoS Solution, which is a major pain.
frontend ALL
bind *:80
bind *:443 alpn h2,http/1.1 ssl crt /etc/haproxy/certs/eduarmor.com.pem
http-request redirect scheme https code 301 if !{ ssl_fc }
http-request redirect code 301 location http://www.%[hdr(host)]%[capture.req.uri] if { hdr(Host) -i eduarmor.com }
mode http

HAProxy redirect based on URL parameter

I need to redirect based on a URL parameter. For example,
curl -X POST 'http://load-balancer:27300/path?appid=1' should always hit app-1
curl -X POST 'http://load-balancer:27300/path?appid=2' should always hit app-2
I tried the below configurations on HAProxy 1.5.18-6.el7, but it redirects to different servers each time. It behaves as if its balance roundrobin.
frontend front
bind *:27300
default_backend back
backend back
acl app1_url urlp(appid) 1
acl app2_url urlp(appid) 2
use-server app1 if app1_url
use-server app2 if app2_url
server app1 192.168.250.11:7300 check
server app2 192.168.250.31:7300 check
For posterity, you should have moved the acl in the frontend section, and then:
use_backend app1 if app1_url
use_backend app2 if app2_url
and also add the corresponding backends for these rules.

How to make HAProxy's SSL redirect and path rewrite (with reqrep) work at the same time?

I need to deploy different apps on the same domain, thus I've set up the backend to rewrite URL with reqrep ^([^\ ]*\ /)appA[/]?(.*) \1\2. It works when I only deploy the HTTP or HTTPS version of the app.
However, if I try to redirect all HTTP traffic to HTTPS, it doesn't work. The problem is that HAProxy has already rewritten the URL and stripped out the /appA part before the redirection. Thus if I try to visit http://myserver.com/appA, the page https://myserver.com will eventually be requested instead of https://myserver.com/appA.
I can't put the redirect rule before the reqrep rule as it seems that HAProxy must process all the rewrites before the redirects.
What can I do to make my configuration work as I intended? This should be obvious but I can't seem to find a relevant answer online.
My configuration:
frontend http_front
bind *:80
reqadd X-Forwarded-Proto:\ http
acl appA_url url_beg /appA
use_backend appA if appA_url
frontend https_front
bind *:443 ssl crt /etc/haproxy/certs/myserver.com.pem
reqadd X-Forwarded-Proto:\ https
acl appA_url url_beg /appA
use_backend appA if appA_url
backend appA
reqrep ^([^\ ]*\ /)appA[/]?(.*) \1\2
redirect scheme https if !{ ssl_fc }
balance roundrobin
server web1 127.0.0.1:5001 check
Use http-request directives, which are processed in declararion order. They are also newer features, and usually cleaner, more intuitive, more flexible, and more internally efficient than reqxxx.
http-request redirect scheme https if ! { ssl_fc }
http-request set-path %[path,regsub(^/appA/,/)]
See http-request. Requires 1.6 or later, where the regsub() converter is available.

HAProxy redirect HTTPS if SSL-certificate is available

I would like to force TSL/SSL/HTTPS if HAProxy has a certificate available for the provided domain. I could just provide a list with domain names, but I would rather have it dynamically so that I do not have to update it over and over again.
This is my current configuration:
frontend public
acl has_ssl hdr(host) -i one.nl two.be three.be four.nl five.nl six.com seven.com eight.net nine.com ten.org
use_backend www-https if has_ssl
default_backend www
backend www-https
redirect scheme https if !{ ssl_fc }
Is there a system variable or something to check if a certificate for the domain name is available?