Redirecting EC2 Elastic Load Balancer from HTTP to HTTPS

RedirectNginxAmazon Ec2HttpsAmazon Elb

Redirect Problem Overview


I want to redirect all the HTTP request to https request on ELB. I have two EC2 instances. I am using nginx for the server. I have tried a rewriting the nginx conf files without any success. I would love some advice on it.

Redirect Solutions


Solution 1 - Redirect

AWS Application Load Balancers now support native HTTP to HTTPS redirect.

To enable this in the console, do the the following:

  1. Go to your Load Balancer in EC2 and tab "Listeners"
  2. Select "View/edit rules" on your HTTP listener
  3. Delete all rules except for the default one (bottom)
  4. Edit default rule: choose "Redirect to" as an action, leave everything as default and enter "443" as a port.

Native redirect listener rule

The same can be achieved by using the CLI as described here.

It is also possible to do this in Cloudformation, where you need to set up a Listener object like this:

  HttpListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      LoadBalancerArn: !Ref LoadBalancer
      Port: 80
      Protocol: HTTP
      DefaultActions:
      - Type: redirect 
        RedirectConfig:
          Protocol: HTTPS
          StatusCode: HTTP_301
          Port: 443

If you still use Classic Load Balancers, go with one of the NGINX configs described by the others.

Solution 2 - Redirect

ELB sets X-Forwarded-Proto header, you can use it to detect if original request was to HTTP and redirect to HTTPS then.

You can try this in your server conf:

if ($http_x_forwarded_proto = 'http') {
    return 301 https://yourdomain.com$request_uri;
}

Take a look at ELB docs.

Solution 3 - Redirect

I had the same problem, in my situation HTTPS was handled entirely by ELB and I didn't know my source domain ahead of time so I ended up doing something like:

server {
  listen 81;
  return 301 https://$host$request_uri;
}

server {
  listen 80;
  # regular server rules ...
}

And then of course pointing the ELB 'https' to the instance port 80 and then the 'http' route to the instance port 81.

Solution 4 - Redirect

The Amazon Elastic Load Balancer (ELB) supports a HTTP header called X-FORWARDED-PROTO. All the HTTPS requests going through the ELB will have the value of X-FORWARDED-PROTO equal to “HTTPS”. For the HTTP requests, you can force HTTPS by adding following simple rewrite rule. For me it works fine!

Apache

You can add following lines in your .htaccess file:

RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI}

Or if you use vhost.conf for managing multiple domains in same EC2 web server then you can add following to the vhost.conf (add it to the domain you want to use https for it):

<VirtualHost *:80>
...
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI}
...
</VirtualHost>

IIS

Install IIS Url-Rewrite module, using the configuration GUI add these settings:

<rewrite xdt:Transform="Insert">
<rules>
<rule name="HTTPS rewrite behind ELB rule" stopProcessing="true">
<match url="^(.*)$" ignoreCase="false" />
<conditions>
<add input="{HTTP_X_FORWARDED_PROTO}" pattern="^http$" ignoreCase="false" />
</conditions>
<action type="Redirect" redirectType="Found" url="https://{SERVER_NAME}{URL}" />
</rule>
</rules>
</rewrite>

Read more here

Solution 5 - Redirect

The htaccess solutions above caused ELB health check to fail. I had some trouble finding the solution until I discovered an article online in which someone had the same issues I had. His solution was to add this to the beginning of the htaccess file instead:

RewriteEngine on 
RewriteCond %{HTTP:X-Forwarded-Proto} ^http$
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

> To allow this and other local requests over HTTP while redirecting > external requests through the ELB to HTTPS, adjust the rewrite > condition to match on http instead of a negative match on https.

Source: [Redirecting HTTP to HTTPS with AWS and ELB][1]

[1]: http://fuzzyblog.io/blog/aws/2017/02/03/redirecting-http-to-https-with-aws-and-elb.html "Redirecting HTTP to HTTPS with AWS and ELB"

Solution 6 - Redirect

It may not be the solution you might be looking for, but another option could be to use AWS CloudFront in addition to ELB. CloudFront gives the option to redirect all incoming HTTP traffic to HTTPS.

Solution 7 - Redirect

Based on @Ulli's answer If you want to configure it using Terraform, here is an example >

resource "aws_alb_listener" "web" {
  load_balancer_arn = "${aws_alb.web.arn}"

  port              = "80"
  protocol          = "HTTP"
  
  default_action {
    type = "redirect"

    redirect {
      port        = "443"
      protocol    = "HTTPS"
      status_code = "HTTP_301"
    }
  }
}

Source

Solution 8 - Redirect

I had strange problem with nginx and ELB configuration. My setup included 3 different services inside one nginx behind ELB. And I had mixed content issue: when your request to ELB is https, but inside ELB http only, and server create relative path to static using http, so browser fails with 'mixed content' issue. And I must create solution for both http/https work without any redirects.

Here is config located in nginx/conf.d/ folder:

# Required for http/https switching
map $http_x_forwarded_port $switch {
  default   off;
  "80"    off;
  "443"   on;
}

This means that we will have knowledge what real client protocol is. As you can see, we will have it in $switch var. And at this moment you use this in all location where you need it:

location ~ /softwareapi/index.php {
  fastcgi_param HTTPS $switch;
  .. other settings here ..
}

With HTTPS setting php application will automatically detect right protocol and carefully build relative path for preventing mixed content issue.

Best regards.

Solution 9 - Redirect

I just went through the process and tested redirects (from ec2 instance shell) with command

curl -Iv [your url]

ex: curl -Iv http://example.com

Requirement

  1. set up Hosted zone for DNS and Name server in AWS Route 53

  2. get certificate using AWS Certificate Manager

  3. add listener on load balancer for port 443 pick the certificate from 2. and the SSL

    • Elastic Beanstalk --> click environment --> Configuration --> Find Load Balancer then click Edit --> Add listener; use SSL Policy of 2016-08 (others may give errors)

What I did is:

  1. Redirect http://yourwebsite.com --> https://www.yourwebsite.com (step 2)
  2. Redirect http://www.yourwebsite.com --> https://www.yourwebsite.com (step 2)
  3. Redirect https://yourwebsite.com --> https://www.yourwebsite.com (step 3)

Steps

1. Went to EC2 Load Balancer

2. Go in to Listener ID HTTP : 80 (Click View/edit rules underneath the Rules column)

Edit default action: (click pencil icon on top, use "Switch to full URL", it will be greyed out until you enter #{port})

  1. change THEN block to Redirect to https://#{host}:443/#{path}?#{query}
  2. Status code:HTTP_301

Add one more action (click + sign on top)

  1. choose IF block Host header is yourwebsite.com
  2. change THEN block to Redirect to https://www.#{host}:443/#{path}?#{query}
  3. Status code:HTTP_301

enter image description here

3. Go back and go in to Listener ID HTTPS : 443 (Click View/edit rules)

Add one more action (click + sign on top)

  1. choose IF block Host header is yourwebsite.com
  2. change THEN block to Redirect to https://www.#{host}:443/#{path}?#{query}
  3. Status code:HTTP_301

Do not edit default action on HTTPS

enter image description here

Solution 10 - Redirect

Here you go with exact answer : Create this file with following name and put the following content in it.

> redirect-to-https.json

[
  {
      "Type": "redirect",
      "RedirectConfig": {
          "Protocol": "HTTPS",
          "Port": "443",
          "Host": "#{host}",
          "Path": "/#{path}",
          "Query": "#{query}",
          "StatusCode": "HTTP_301"
      }
  }
]

Use this awscli command to create a listener rule on port 80 with HTTP protocol which will redirect all traffic to HTTPS port.

> aws elbv2 create-listener --load-balancer-arn > arn:aws:elasticloadbalancing:us-east-1:12345678910:loadbalancer/app/demo1-alb/b4d5fbc78965417f > --port 80 --protocol HTTP --default-actions file://redirect-to-https.json

Solution 11 - Redirect

Create a file .ebextensions/00_forward_http_to_https.config with the following content:

files: 
  /tmp/deployment/http_redirect.sh:
    mode: "000755"
    content: |
      APP_URL=`/opt/elasticbeanstalk/bin/get-config environment --output yaml | grep -oP 'APP_URL: \K([^\s)\"](?!ttp:))+'`
      sed -ie 's@$proxy_add_x_forwarded_for;@$proxy_add_x_forwarded_for;\n        if ($http_x_forwarded_proto = 'http') { return 301 https://'"$APP_URL"'$request_uri; }@' /tmp/deployment/config/#etc#nginx#conf.d#00_elastic_beanstalk_proxy.conf

container_commands:
  http_redirect:
    command: "/tmp/deployment/http_redirect.sh"

Make sure to set the APP_URL environment variable from the AWS management console beforehand.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAmit BadhekaView Question on Stackoverflow
Solution 1 - RedirectUlliView Answer on Stackoverflow
Solution 2 - RedirectDmitry MukhinView Answer on Stackoverflow
Solution 3 - RedirectTylerFowlerView Answer on Stackoverflow
Solution 4 - RedirectIman SedighiView Answer on Stackoverflow
Solution 5 - RedirectomikesView Answer on Stackoverflow
Solution 6 - RedirectMojoJojoView Answer on Stackoverflow
Solution 7 - RedirectcallmemathView Answer on Stackoverflow
Solution 8 - RedirectOleg MykolaichenkoView Answer on Stackoverflow
Solution 9 - RedirectACHEERView Answer on Stackoverflow
Solution 10 - RedirectSIddharthView Answer on Stackoverflow
Solution 11 - RedirectAndresView Answer on Stackoverflow