Reputation: 629
I have a cluster (that could have N instances in autoscaling) and I have a service with a website done in Node/Express.
I have a Elastic Load Balancer which has a Target Group and the Listener points certain path to this target group.
Everything works as expected, the website loads, and I can access with and without https but how could I make the HTTPS mandatory redirecting from HTTP? I don't have any proxy in ECS (don't know if nginx-proxy supports several instances in my cluster)
Thanks
Upvotes: 1
Views: 1578
Reputation: 8023
Basically, AWS load balancer now supports https redirects from the http listener rules (provided your application is doing the rewrites of the URLs within it from http to https).
Navigation: Load Balancer > Listeners > HTTP:80 > view/edit rules > add rule (above default). The rule should look like:
IF:
Source IP is 0.0.0.0/32
THEN:
Redirect to HTTPS://#{host}:443/#{path}?#{query}
Status code: HTTP_301
NOTE: There should be a https listener also present (with valid certificates, can be self signed also) listening on port 443 for this to work.
Upvotes: 0
Reputation: 19728
Update Jul 25, 2018: Elastic Load Balancing Announces Support for Redirects and Fixed Responses for Application Load Balancer. You can find more information in AWS listener rules.
You cannot do the HTTP to HTTPS redirect on your ELB/ALB.
There are multiple approaches to do it in AWS.
Note: Since you are using Node/Express its a best practice to have a web server like Nginx in front of it. Check the following Stackoverflow Q/A for more details.
Upvotes: 3
Reputation: 96
Since you are using Express, you can listen to all incoming requests and check if the x-forwared-proto header is "http". If it is, redirect to https. The Express middleware function will look like this:
function forceHttps(req, res, next) {
const xfp =
req.headers["X-Forwarded-Proto"] || req.headers["x-forwarded-proto"];
if (xfp === "http") {
const secureUrl = `https://${req.headers.hostname}${req.url}`;
res.redirect(301, secureUrl);
} else {
next();
}
}
... or you can just use an NPM package designed for this specific use case: https://www.npmjs.com/package/@crystallize/elasticloadbalancer-express-force-https
Install
npm i --save @crystallize/elasticloadbalancer-express-force-https
Usage
const express = require('express');
const forceHttps = require('@crystallize/elasticloadbalancer-express-force-https');
const server = express();
server.use(forceHttps());
More information in our blog post about this: https://snowball.digital/blog/force-https-behind-elastic-load-balancer-on-a-nodejs-application
Upvotes: 0
Reputation: 7185
I don't think the ALB/ELB can do the redirect on its own.
This AWS article describes how to set the redirect for nginx:
server {
listen 80;
server_name www.example.org;
if ($http_x_forwarded_proto != "https") {
rewrite ^(.*)$ https://$server_name$REQUEST_URI permanent;
}
}
Another option in this SO answer:
if ($http_x_forwarded_proto = 'http') {
return 301 https://yourdomain.com$request_uri;
}
Regarding having multiple instances of the app, what we do is putting the app server under an internal ALB and then create another service for the nginx server to act as a kind of "application gateway", this time with an external ALB with the SSL certificate installed. Nginx directs requests to the internal app ALB. This is similar to the architecture shown in Remind's Empire.
Upvotes: 1