codiaf
codiaf

Reputation: 629

Force ssl within a Node/Express web using AWS ECS

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

Answers (4)

Devaroop
Devaroop

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

Ashan
Ashan

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.

  • Use AWS CloudFront in front of your application and do the SSL redirect there. You have the benefit of edge caching at CDN but will cost more.
  • Having a Nginx proxy container like Jwilder Nginx Proxy in front of your NodeJS/Express containers and enforce redirect at proxy. This is an approach if you have common rules for all of your NodeJS/Express containers such as HTTP to HTTPS redirect.
  • Use a docker image for NodeJS/Express containers which has Nginx internally.

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

user2439455
user2439455

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

dukebody
dukebody

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

Related Questions