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

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.

Related

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

Rancher/HAProxy: https redirect not working

I have set up a HAProxy lb in front of my services.
According to the HAProxy documentation, in order to achieve 80 --> 443 redirect, the following line should be added to the
Custom haproxy.cfg
tab when configuring the service:
redirect scheme https code 301 if !{ ssl_fc }
This does not seem to work since when I am accessing my site on http:// it stays on 80.
Any suggestions?
Using:
"CATTLE_RANCHER_SERVER_VERSION=v1.6.14"
rancher/lb-service-haproxy:v0.7.15
The way that i resolved this, is the next:
Add a new selector rule listening in the port 80 and HTTP protocol, put any what you want in target (foo=bar per example).
Add this in the Custom haproxy.cfg tab
frontend http-redirect
bind *:80
mode http
redirect scheme https code 302 if !{ ssl_fc }

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?

HA Proxy rule - 404 not found

I have configured below rule in HA Proxy. I get 404 not found when I try to hit http://haproxy_ip/service
frontend http-in
bind 10.254.23.225:80
acl has_service path_beg /service
use_backend service_server if has_service
backend service_server
balance roundrobin
cookie SERVERID insert
option httpchk HEAD /check.txt HTTP/1.0
option httpclose
option forwardfor
server server1 192.168.2.1:9000 cookie server1 check
backend doesnt have /service in itself. I use haproxy to have virutal path in url.
With the current configuration, /service/test.txt will trigger the acl has_service and will send /service/test.txt to your backend, without changing the url.
If you want to change the url (proxying /service in the frontend to / in the backend), you should add the following line in your backend:
reqrep ^([^\ ]*)\ /service(.*) \1\ \2
This will remove /service from the proxied request.
Edit:
HAProxy won't rewrite the html output: your assets won't get a leading /service/ and won't be served correctly.
When you proxy requests, it is way easier to keep the same path: proxying / to / or /myapp/ to /myapp/ for example. If you proxy /a to /b/c, the proxy itself will need to rewrite the response: <img src="/a/test.png"> needs to be changed to <img src="/b/c/test.png">. Or worse, <img src="../c/test.png" />. Add relative references in html, js and css too. I'm not sure it's doable with HAProxy.
If you can change the application and deploy it on /service/, you will avoid a lot of issues. Using an other vhost (service.yourdomain.com for example) can solve this issue too.
If not, I'm not sure HAProxy is the right tool here, I'd try apache 2.4 with
mod_proxy_html (but not before trying really hard to deploy the app on /service/).

HAProxy - Redirect traffic of one domain to https and other domains to http only

I am using dedicated servers to host 4 domains and 3 subdomains on Centos & WHM. Recently planned to use HAProxy for load balancing between them.
What I am trying to achieve is to redirect all the traffic of one particular domain to https using HAProxy configuration on frontend because I am terminating the SSL of that one particular domain at HAProxy.
here's what i have used
frontend www-https
bind haproxy_www_public_IP:443 ssl crt /etc/ssl/private/example.com.pem
reqadd X-Forwarded-Proto:\ https
default_backend www-backend
backend www-backend
redirect scheme https if !{ ssl_fc }
server www-1 www_1_private_IP:80 check
server www-2 www_2_private_IP:80 check
I have googled for solution but most of the solution available are telling to redirect all the traffic to https or http.
If I understand correctly, you want one domain (in the configuration below it is httpsonlydomain.com) to only be accessible by https and all http requests to that domain get forwarded onto https. For the other domains they can work by either http or https with no forwarding. Finally I have assume that all four domains (including httpsonlydomain.com) will use the www-backend backend.
If that is the case then this should do the trick:
frontend www-http
bind haproxy_www_public_IP:80
acl https_domain hdr(host) -i httpsonlydomain.com
redirect scheme https if !{ ssl_fc } https_domain
default_backend www-backend
frontend www-https
bind haproxy_www_public_IP:443 ssl crt /etc/ssl/private/example.com.pem
default_backend www-backend
backend www-backend
server www-1 www_1_private_IP:80 check
server www-2 www_2_private_IP:80 check
Hope that helps.