Detect HTTPS without SSL Termination - haproxy

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.

Related

Consult for redirecting http to https via 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.

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.

Rewrite HTTP to HTTPS on Mojolicious

I am running a Mojolicious app on Hypnotoad. It is listening to port 443 and it can be accessed through https.
how can I forward all HTTP request to HTTPS?
According to this post your server listen only 443 port. So you should add another application to handle 80 port.
The best way to add nginx or apache in front of hypnotoad and do it there (redirect, rewrite).
But if you don't want to have nginx, you may write Mojolicious application
which listen two ports and have hook before_dispatch wich handle all requests and make redirect changing only scheme.
If you want i may to attempt to write such minimal example.
Upd. I decide to add example
You can't, at least not directly. While you could use iptables or similar to forward port 80 to 443, in practice that wouldn't work because the browser doesn't expect to have to do an SSL handshake for a plain HTTP URI. You have to run a trivial web app on port 80 (probably with a separate Hypnotoad or similar) that answers every request with a redirect to HTTPS -- probably either to some login page or to the same URI as requested with just the scheme changed.

Nginx redirect https www to https non-www

I have SSL cert to my domain mydomain.com (without www.)
Nginx config:
server
{
server_name www.mydomain.com;
return 301 $scheme://mydomain.com$request_uri;
}
All redirects work fine except https://www.mydomain.com -> https://mydomain.com.
Every browser show me an alert with message like this:
This Connection is Untrusted
You have asked Firefox to connect securely to www.mydomain.com,
but we can't confirm that your connection is secure.
What should I do?
No, it is not possible. HTTPS is HTTP inside SSL, so to get the HTTP redirect first the SSL connection has to be established and verified - and this is the steps where it fails if you don't use a certificate not trusted by the browser (e.g. self-signed or where the hostname does not match the certificate).

Force HTTPS in Neo4j configuration

Is is possible force HTTPS URLs even when the X-Forwarded-Host header is not present?
Update:
We are using HAProxy in front of the Neo4j server. The configuration is
frontend proxy-ssl
bind 0.0.0.0:1591 ssl crt /etc/haproxy/server.pem
reqadd X-Forwarded-Proto:\ https
default_backend neo-1
This works well when every connection contains only one request. However, for Neo4j drivers which uses keep-alive (like Py2neo), the header is added only to the first request.
Without the X-Forwarded-Proto header, the generated URLs are http://host:1591, instead of https://host:1591.
According to the HAProxy documentation, this is the normal behavior:
since HAProxy's HTTP engine does not support keep-alive, only headers
passed during the first request of a TCP session will be seen. All subsequent
headers will be considered data only and not analyzed. Furthermore, HAProxy
never touches data contents, it stops analysis at the end of headers.
The workaround is to add option http-server-close in the frontend, so it will force that every request is in its own connection, but it will be nicer if we can support keep-alive.
Put something like Apache or Nginx in front of your Neo4j server to perform that task.
In terms of py2neo, I can add some functionality to cater for this situation quite easily. What if I were to include X-Forwarded-Proto: https for all https connections? Would that cause a problem in cases where a proxy isn't used?