1

I have a site example.com, where I want all requests to that hostname to be directed to https://www.example.com. It's currently running in node on Elastic Beanstalk.

I have the following solutions for redirecting, but unsure about how to do step 3:

Also, is this the best way to do things (or is there a better way in general to achieve the below?)

1) http://example.com -> https://www.example.com (DONE - via A-record to a S3 bucket - example here).

2) http://www.example.com -> https://www.example.com (DONE - via a HTTPS redirect in expressJS - example here).

3) https://example.com -> https://www.example.com (How do I do this?) - this current gives a ERR_CONNECTION_TIMED_OUT.

HHH
  • 149
  • 2
  • 12
  • What DNS service are you using? Route53? – Mark B Jan 07 '17 at 15:39
  • I did look and NodeJS apps on Elastic Beanstalk run behind an nginx proxy. It would be a bit cleaner (and marginally faster) to implement all your http => https and !www => www redirects with nginx rather than node. You can do this with .ebextensions: http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_nodejs.container.html#nodejs-platform-proxy – Dave Maple Jan 07 '17 at 18:31

1 Answers1

4

You'll probably want to handle the www subdomain and the naked apex differently.

1) http://example.com -> https://www.example.com

The easiest route to handle the naked (apex) domain redirects is to go into Route53 and and setup the apex to use an A alias record to an S3 bucket target. In the S3 bucket you can enable "Redirect all requests to another domain" and redirect to https://www.example.com.

This solution would only work for http requests though and not https since S3 won't terminate SSL for an https request. See #3 for a solution that would work for both http and https.

2) http://www.example.com -> https://www.example.com

You can do same domain www http => https redirects using the X-Forwarded-Proto HTTP header in your application. It will have a value of either http or https. If you receive http you could redirect to https.

An apache example would look like this:

RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule . https://%{HTTP:Host}%{REQUEST_URI} [L,R=permanent]

An nginx example could look like this:

if ($http_x_forwarded_proto != "https") {
  rewrite ^(.*)$ https://$server_name$1 permanent;
}

Alternatively, you could front your Elastic Beanstalk app with Cloudfront and implement an http => https redirect there. In "Behavior Settings" you can check the radio button "Redirect HTTP to HTTPS".

3) https://example.com -> https://www.example.com

You will need an SSL cert that has a subject alternate name covering example.com and www.example.com. You could get this for free with AWS Certificate Manager. You can "Add more names" which would allow you to cover *.example.com and example.com in a single certificate. Certificate Manager is fully integrated with Cloudfront so it's a nice option.

Cloudfront Option:

Cloudfront is a pretty good option here -- especially if you use it to front the whole app (apex and www).

Within Cloudfront in "Alternate Domain Names (CNAMEs)" you'd need to add both example.com and www.example.com (separate these with a comma or newline). You'll also specify your digital certificate covering both domains.

Elastic Beanstalk Option:

If you don't want to use Cloudfront you could terminate SSL at the Elastic Load Balancer instead for both apex and www and implement the same !www redirect using your application tier http service (apache, nginx etc.). Just add the SSL cert covering both domains (apex and www subdomain).

Implement the non-www redirect:

With either termination option you'll get a request for https://example.com going back to your origin server on Elastic Beanstalk, however you will need to return a 301 that directs the browser to https://www.example.com at the application tier.

An apache example:

RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

An nginx example:

server {
    server_name "~^(?!www\.).*" ;
    return 301 $scheme://www.$host$request_uri;
}

Route53 Alias Record for Apex:

With either solution you'll need a Route53 A Alias record on the apex to make this work as CNAME records aren't supported for the apex (naked) domain. You'd specify the Elastic Beanstalk target or Cloudfront target.

Dave Maple
  • 8,102
  • 4
  • 45
  • 64