How to manage 3xx response from target group in ALB? - odoo

I deployed an Odoo instance on ECS + FARGATE as a service, which is assigned to a target group.
On ALB I have a listener on port 443 with ACM that redirects the traffic on that target group.
The connection is working, I can reach the Odoo service from the ALB.
The problem is, Odoo can respond with 3xx codes, and I can see the url changing on the browser address bar. But instead of loading the new page, I get an error.
If resend the request directly with this same url, the one resulting from the redirect, the page loads as expected.
If I connect to the service directly, without ALB, it works fine.
From what I could understand, the ALB doesn't manage the 3xx response codes from the target group, so it gives an error.
What can i do to resolve this redirect problem?
EDIT:
Problem solved, here is what i tried:
I tried setting the listener on HTTP instead of HTTPS, and it worked fine.
After that, i reconfigured the listener on HTTPS, and added an HTTP listener which returned a fixed response. Tried to click an url of the server which returns a 3xx code, and instead of an error i got the fixed response.
In practice, the server behind the ALB listens on port 80, so when it issues a redirect, it does so on HTTP. The ALB receives in as HTTP, but wasn't listening. It was configured only on HTTPS. Hence the error.
I resolved configuring two listeners:
an HTTPS listener which forwards traffic towards the target group
an HTTP listener which redirects to HTTPS

On ALB I have a listener on port 443 with ACM that redirects the traffic on that target group.
It forwards traffic to the target group. It does not redirect the traffic.
The problem is, Odoo can respond with 3xx codes, and I can see the url changing on the browser address bar. But instead of loading the new page, I get an error.
Including the details of that error in your question would be a key detail that needs to be included in your question. You need to edit your question to include the details of that error in order to get more detailed help.
If resend the request directly with this same url, the one resulting from the redirect, the page loads as expected.
If resending the exact request with no changes works, then there is some issue in your server software or something. There is nothing about using an ALB that would make sending the request a second time suddenly work.
From what I could understand, the ALB doesn't manage the 3xx response codes from the target group, so it gives an error.
That isn't correct. The ALB will happily send any response, with any HTTP response code, from the server back to the client. The only issue you may run into is if the health-check URL configured on the target group is sending something other than a 200 HTTP response. The health check requests are the only requests that the ALB/Target Group examine the response code on.

Related

How to pass original URI, with arguments, to Traefik ErrorPage handler specified in `query`?

I'm trying to use nginx to serve a custom error page using the Error Page middleware so that 404 requests to a lambda service (which I don't control) can be handled with a custom error page. I want to be able to get the context of this original request on that error page, either in Nginx for further forwarding, or else as a header for further handling e.g. in PHP or whatnot so I can provide contextual links on the 404 page.
However, right now after the redirection to Nginx in Traefik's ErrorPage middleware it seems the request has lost all the headers and data from the original service query.
The relevant part of my dockerfile:
traefik.port=8080
traefik.protocol=http
traefik.docker.network=proxy
traefik.frontend.rule=PathPrefix:/myservice;ReplacePathRegex:^/myservice/(.*) /newprefix/$$1
traefik.frontend.errors.myservice.status=404
traefik.frontend.errors.myservice.service=nginx
traefik.frontend.errors.myservice.query=/myservice-{status}
Nginx receives the forwarded 404 request, but the request URI comes through as nothing more than the path /myservice-404 specified in query (or /, if I omit traefik.frontend.errors.myservice.query). After the ReplacePathRegex I have the path of the original request available in the HTTP_X_REPLACED_PATH header, but any query arguments are no longer accessible in any header, and nginx can't see anything else about the original URI. For example, if I requested mysite.com/myservice/some/subpath?with=parameters, the HTTP_X_REPLACED_PATH header will show /myservice/some/subpath but not include the parameters.
Is it possible in Traefik to pass another service the complete context about the original request?
What I'm really looking for is something like try_files, where I could say "if this traefik request fails, try this other path instead", but I'd settle for being able to access the original, full request arguments within the handling backend server. If there was a way to send Nginx a request with the full path and query received by Traefik, that would be ideal.
tl;dr:
I am routing a request to a specific service in Traefik
If that request 404s, I want to be able to pass that request to Nginx for further processing / a contextual error page
I want Nginx and/or the page which receives the ErrorPage redirect to be able to know about the request that 404'd in the service
Unfortunately this is not possible with Traefik. I tried to achieve something similar but I realized that the only information that we are able to pass to the error page is the HTTP code, that's it.
The only options available are mentioned in their docs: https://doc.traefik.io/traefik/middlewares/errorpages/

Using cloudflare flexible ssl option causes login form to refresh instead of sending request

I am using cloudflare's "flexible ssl" as an intermediary between client and my site.
After setting this up, I went to the browser and tried accessing my site via https:
https://example.com/login
and everything works. I fill in my login info and log in successfully and am not on http://example.com . I manually enter https://example.com/* where * is many other pages and it all works fine.
Now I want to redirect all requests to use the seemingly working https. So i go to my cloudflare account on their website and create a page rule : http://example.com/* to always use https.
Now I go to example.com/login and successfully redirected to https://example.com/login, I fill in my log in information and submit the login form , the page refreshes and I am back to https://example.com/login with an empty login form.
Anyone know what the problem is or how to help troubleshoot?
I am using laravel as a framework for the site and apache as the webserver.
create a page rule : http://example.com/* to always use https
Noted. Be aware that CloudFlare does this by accepting every HTTP request on http://example.com/* and returning a 301 redirect to the equivalent HTTPS request. The browser completes the redirect by sending a GET request to the HTTPS URL.
I fill in my log in information and submit the login form
Check the login form source carefully and check what URL the login form is submitted to. My guess is that the form is submitted to http://example.com/login or something similar. CloudFlare will accept the POST request to http://example.com/login and return a 301 redirect to https://example.com/login -- which your browser will complete as a GET request and hence not sending the login data.
So your best solution is to make sure that your login form POSTs to the correct HTTPS URL not to the HTTP URL.
That's my best guess anyway.
how to help troubleshoot?
Ensure that you are using different log files to distinguish between HTTP and HTTPS requests on your server.
Some other suggestions:
Get a Let's Encrypt SSL certificate and put that on your site so that the communication between CloudFlare and your site is all SSL. https://letsencrypt.org/
Ensure that HSTS is turned on for all of your HTTPS requests so that the browser will know not to send any requests to any HTTP URLs.
Create a development server where you can test all of this working with HTTPS between the browser and the web server without CloudFlare. Once you've got it all working in HTTPS mode without CloudFlare then you can try it with CloudFlare and you should get essentially the same results. Your problem is with the HTTP -> HTTPS switch, not specifically with CloudFlare.

Issue with request body in OPTIONS or DELETE request with google load balancer

My server side setup is like this : I have a google compute engine instance running nodejs server. It sits behind https load balancer.
So the issue is that if OPTIONS type request is sent with body(payload) to load balancer ip, it sometimes fail with 502. I have checked that in all these requests, node server is returning and logging correct responses. It works perfect if the request body is left empty.
However, when I directly hit GCE's ip, it works fine whether or not request body is there or not.
For e.g
this is the load balancer ip (with ssl enabled)
OPTIONS https://130.211.14.60/health
this is the direct GCE machine ip (without ssl)
OPTIONS http://104.199.159.212:8002/health
I have checked by sending requests multiple times(literally hundreds of times) using Postman app.
And this issue is only with DELETE and OPTIONS type requests. GET/POST/PUT works perfectly fine.
Is there anyone who can point me what the issue could be and how to solve it.
From Google's docs -
The HTTP(S) load balancer does not support sending an HTTP DELETE with a body to the load balancer. Such requests will receive an error message: Error 400 (Bad Request)!! Your client has issued a malformed or illegal request. Only DELETE requests without bodies are supported.
More info here.
This feature is now supported by Google Load Balancer, released in Dec '18.
More info here.

Browsing to IP and port number displaying raw html 400 bad request

Setup HTTPS and a redirect from HTTP to HTTPS. Browsing to just the IP address with or without HTTP and HTTPS works great and redirects perfectly. But while browsing to X.X.X.X:443 the web server is displaying the 400 bad request in raw html. Can I either disable the 400 bad request or be able to redirect those requests to HTTPS? Please help. Thanks!
If such is possible, it would depend on which web server you are using and you didn't specify that. However...
Doing so would actually be a bad idea as it would encourage people to use HTTP (no S) to connect to your secure server. In doing so, they would send their request in plaintext. If the system just returned a "301 Moved Permanently" to the HTTPS url, the second request (with reply) would be protected but you still would have leaked the request to a potential attacker during the first attempt.

Reverse proxy mode Apache intercept or trap 302 responses from backend server and redirect internally without sending 302 response back to client

Does anyone knows how to tell Apache, in reverse proxy mode, to intercept or trap 302 (or 30x) responses from backend server and redirect internally without sending 30x response back to client?
Ultimately, the backend server the response is redirected to would not be accessible from the outside (or not listed in Apache conf).
My situation:
I have web_server_A and web_server_B listening on port 6666 and 7777. These ports are not accessible from outside, but are accessible from the inside.
I can eventually change the behavior of web_server_A, but not the one of web_server_B.
Apache is listening on ports 80/443, accessible from the outside and is acting as a reverse proxy sending requests addressed to web_server_{A,B}.example.com to web_server_{A,B}
The client asks Apache for web_server_A.example.com/foo. Apache proxies the request to web_server_A which makes some stuff and then sends back to Apache a HTTP/302 response pointing on web_server_B.example.com/bar/secret_token. Apache sends back the 302 response to the client which then sends Apache an HTTP request for web_server_B.example.com/bar/secret_token. Apache proxies the request to web_server_B, which replies something (usually it sends back some big file).
My problem:
I don't want the client to know about the url web_server_B.example.com/bar/secret_token, and ultimately I don't want web_server_B to be accessible from outside.
web_server_A could make the request to web_server_B and then send back the answer from web_server_B without issuing a 302 reply. But, the answer from web_server_B might take some time to come, might be quite big, and web_server_A should not spend too much time on any request (it has no ability for handling big files).
So I thought about a "302 trapper" feature that would be nice if existing, but so far haven't fund anything on the web on how to do that. Any idea?
As a reverse proxy, Apache won't be able to "block replies." It's not a censor.
You could write something like this yourself, though.
using ProxyPassReverse directive, web_server_A will modify Location header sent by web_server_B, so the client won't know about him.
to trap redirect from upstream server you can also edit Location header. For instance "Header unset Location" will show apache default 30X error page