Consult for redirecting http to https via HAproxy - haproxy

I am trying to configure the HAproxy to make it redirect the http traffic to https, but Chrome failed with "ERR_SSL_PROTOCOL_ERROR". However, if I used https directly it will work.
For example:
If I typed https://:5443, it will display the page of backend servers.
If I typed http://:5006, it should be redirected but just failed with the error mentioned above.
Here is my config:
frontend simple_webapp
mode http
bind *:5006
bind *:5443 ssl crt /root/Downloads/simple_webapp_all.pem
http-request redirect scheme https unless { ssl_fc }
default_backend simple_webapp
backend simple_webapp
balance roundrobin
server centos8-1 <server ip1>:5006 check
server centos8-2 <server ip2>:5006 check
Please correct me if there is any misconfiguration.

You probably expected that you changed port with scheme, but you haven't. Your request to http://foo:5006/ gets redirected to https://foo:5006, which doesn't support SSL. If you omit port in URL then browsers and web clients are smart enough to use port 80 for HTTP and 443 for HTTPS. That's why it works for default ports.
So try to change your redirect to something like this:
http-request redirect prefix https://your_domain_as_explicit_string:5443 unless { ssl_fc }
You can experiment with headers, like
http-request redirect prefix https://%[hdr(host),regsub(:5006,:5443)] unless { ssl_fc }
hdr(host) includes in this case :5006, so that's changed with regsub

Once I changed the port from 5006 to others, it works fine.
No clue what happened on this port.

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 - Configure Name and Port Proxies for different backends

Background: We have a series of interconnected applications SSL and all that we need to test putting a load balancer in front of. We're looking to publicly expose '443' to the end-users but have HAProxy proxy/redirect to the required internally exposed tcp-listeners. We're testing this implementation with haproxy and thought it would be a bit easier than either it is or we're making it to be.
https://example.com/app1 -> backend of 6 different hosts (or the
internal fqdn (not sure which would be correct)) on 30001
https://example.com/app2 -> backend of 6 different hosts (or the
internal fqdn (not sure which would be correct))on 8443
...
We've tried a number of different frontend/backend configs but can't seem to make it work as we intend. If anyone can tell me what I'm doing wrong, I'd appreciate it. Also we do not want SSL to terminate on the HAproxy which is why we aren't providing certs in the bind statement.
test1:
frontend test
bind *:443
acl path_spgen path_beg -i /app1
use_backend be_spgen if path_spgen
backend be_spgen
server host-01 x.x.x.x:30001
test2:
frontend test
bind *:443
acl path_spgen path_beg -i /app1
http-request redirect scheme https code 301 if !{ ssl_fc }
http-request redirect code 301 location https://example:30001 if path_spgen
backend be_spgen
server host-01 x.x.x.x:30001
any help would be greatly appreciated.

Redirecting HTTP to HTTPS behind load balancer

I'm moving an ASP.NET Core application to AWS Beanstalk and I'm having an issue forcing HTTPS for all requests. The useful error from the logs is:
Failed to determine the https port for redirect.
According to the docs on enforcing HTTPS:
If requests are forwarded in a reverse proxy configuration, use Forwarded Headers Middleware before calling HTTPS Redirection Middleware. Forwarded Headers Middleware updates the Request.Scheme, using the X-Forwarded-Proto header
Based on my setup it looks like it should be correct:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
// aws ssl termination
app.UseForwardedHeaders(new ForwardedHeadersOptions() {
ForwardedHeaders = ForwardedHeaders.XForwardedProto
});
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
} else {
app.UseExceptionHandler("/error/500");
app.UseHsts();
}
app.UseHttpsRedirection();
// lots of other stuff removed for brevity
}
The load balancer is accepting requests on HTTP (80) and HTTPS (443) and the application is setup in IIS to only accept requests on HTTP (80). This and the error message makes it seem related to an announcement they made, but based on the docs I would expect the forward headers middleware to resolve the issue.
Update
If instead of using UseHttpsRedirection I switch to using the RequireHttpsAttribute and AddRedirectToHttps rewrite middleware the redirects work correctly. It's just the UseHttpsRedirection middleware that I can't get working.
Okay me summarize the comments:
My load balancer isn't performing the HTTPS redirection, so that's why I think I need the middleware. Unless I'm misunderstanding?
So you send an HTTP request to the proxy, which is redirected to your application and then you get that error?
This is because the X-Forwarded-Proto headers have the value http and the Https Redirection middleware won't recognize it as secure protocol and try to redirect.
As per documentation, https configuration is required for the UseHttpsRedirection:
A port must be available for the middleware to redirect an insecure request to HTTPS. If no port is available:
Redirection to HTTPS doesn't occur.
The middleware logs the warning "Failed to determine the https port for redirect."
HTTPS requests (to the proxy) on the proxy should then work, since the X-Forwarded-Proto header are set to https and the redirection Middleware should skip it.
In this case, you have to configure https on the application too (since its required for the middleware). It can be a self-signed certificate, in a reverse proxy configuration it the 443 on the ASP.NET Core app should never be hit. You don't even have to expose the port (when using Docker).
Alternatively, handle the https redirection on the reverse proxy itself. This is the better approach, as the requests will never hit your application in the first place unless its https.

Detect HTTPS without SSL Termination

I am trying to find out if https is in the address bar, as I have SSL termination before the HAPROXY, but I want HAPROXY to do the redirect if it is HTTP (a bit of an odd request i know).
I tried the:
redirect scheme https if !{ ssl_fc }
But it ends up in a never ending loops because it the packets already don't have SSL. Is there another way to get the prefix on a address bar? Also it does it for multiple domains, so trying to do this with a wildcard.
I have SSL termination before the HAPROXY
I assume you mean SSL is terminated on an ELB?
If so:
redirect scheme https unless { hdr(x-forwarded-proto) -m str https }
ELB in http mode adds X-Forwarded-Proto: https on SSL connections. The value is set to http otherwise. Generate a redirect unless the header value matches what you expect.

how to balance to a specific server if hostname matches x.domaine.com (Haproxy)

as mentioned in the title, i've set an Haproxy loadbalancer with a basic configuration, what i'd like to do is to always redirect request to the first server if the hostname matches x.domaine.com, but keep the balancing for domaine.com, is it possible with Haproxy, and if so how can i do it.
her's my configuration
listen webcluster *:80
mode http
balance roundrobin
option httpchk HEAD / HTTP/1.0
option forwardfor
cookie LSW_WEB insert
option httpclose
server bigSRV 192.168.1.10:8082 cookie LSW_WEB01 check
server miniSRV 192.168.2.10:8082 cookie LSW_WEB01 check
thanks in advence
after hours of digging i finally got it to work, so i'm going to answer my own question in case if samone have the same issue
generally i created a frontend that listen on port:80 and in which i defined 2 ACLs that uses the "if" statement to check the http header and then redirect to one of the backends defined, if no request matches the conditions, we redirect to default backend, here's how it's done (on haproxy.cfg) :
frontend http-proxy
bind *:80
acl is_www hdr(host) -i www.domain.com
acl is_x hdr(host) -i x.domain.com
use_backend clusterWWW if is_www
use_backend clusterX if is_x
default_backend clusterWWW
backend clusterWWW
server bigSRV 192.168.1.10:8082 cookie LSW_WEB01 check
server miniSRV 192.168.2.10:8082 cookie LSW_WEB01 check
backend clusterX
server bigSRV 192.168.1.10:8082 cookie LSW_WEB01 check