23. March 2017 00:18
by Aaron Medacco
3 Comments

Enforcing HTTPS For ASP.NET Applications Hosted on EC2 Behind an AWS Elastic Load Balancer

23. March 2017 00:18 by Aaron Medacco | 3 Comments

Note: This post addresses issues with infinite redirects when attempting to enforce HTTPS using an Application Load Balancer. Those using a Classic Load Balancer should not have this issue if they are passing HTTPS traffic to instances on port 443 and HTTP traffic to instance on port 80. Application Load Balancers only allow one forwarding port to instances, which can cause issues outlined in this post.

If you've ever managed ASP.NET web applications hosted on EC2 that are load balanced by an Application Load Balancer, you may have run into issues enforcing users to communicate over SSL. Having SSL termination occur on the ELB is common practice, and removes some work from the instances themselves. In fact, this is a primary use for the AWS Certificate Manager. Find out how to get an SSL certificate for your ELB in my earlier post on provisioning an SSL certificate using AWS Certificate Manager.

 AWS Elastic Load Balancer

The traditional method for enforcing requests to occur with HTTPS instead of HTTP with an ASP.NET web application is to use the URL Rewrite Module within IIS. A quick Google search for how to do this will result in numerous examples using web.config entries that look like or are very similar to the following:

<rule name="HTTP to HTTPS redirect" stopProcessing="true">
  <match url="(.*)" />
    <conditions>
      <add input="{HTTPS}" pattern="off" ignoreCase="true" />
    </conditions>
  <action type="Redirect" redirectType="Permanent" url="https://{HTTP_HOST}/{R:1}" />
</rule>

This can result in a series of infinite redirects when you try to visit a webpage. This happens because SSL is being terminated on the Application Load Balancer. That means that when requests come in to the load balancer over HTTPS, they are sent to the EC2 instances over HTTP. Looking at our rewrite rule configuration, these requests will then be redirected to use HTTPS, which will come in via the load balancer, ad infinitum. Thus, regardless of what protocol users visit your website with, they will never land on a page due to the cycle.

However, this doesn't mean we can't use the URL Rewrite Module for IIS to enforce SSL usage of our site. I'm going to give some credit to Ross Pace at Stack Overflow for answering his own question regarding this very issue. In his answer, you'll find the following rule which accomplishes what we're after:

<rule name="Force Https" stopProcessing="true">
   <match url="healthcheck.html" negate="true" />
   <conditions>
       <add input="{HTTP_X_FORWARDED_PROTO}" pattern="https" negate="true" />
   </conditions>
   <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" />
</rule>

This gets around our issue. But why?

You can see the rule does not take effect (negate="true") if the {HTTP_X_FORWARDED_PROTO} header has a pattern of HTTPS. This header forwards the protocol that was sent to the application load balancer. Therefore, if the user used HTTPS to connect to the load balancer, there is no need to redirect. If the value is anything else, that means we need to perform the redirect. Simple.

You'll also notice that this rule is ignored if the URL matches "healthcheck.html". As explained in his response, this is required to prevent the ELB health checks from failing because of URL Rewrite Module. You can substitute the URL value for whichever page you are using for your own ELB health check. 

Hopefully this saves some .NET developers from walking outside with a pistol. :)

Cheers!

1. January 2017 16:55
by Aaron Medacco
0 Comments

Setting up SSL/TLS Certificates on an Amazon Elastic Load Balancer w/ ACM

1. January 2017 16:55 by Aaron Medacco | 0 Comments

Securing your web traffic using SSL/TLS certificates is a growing standard. Even for small websites, with how cheap SSL/TLS certificates are, there's no excuse not to use them. For those using Amazon's Elastic Load Balancing service to distribute their traffic, the following is how you would establish secure communication without needing to buy and install certificates on your instances. Certificates provisioned using Certificate Manager are free of charge, and can be used with Amazon's Elastic Load Balancing & AWS CloudFront services.

Admittedly, I omitted one important step the first few times I did this because apparently I can't read.

Certificate Manager 3

Creating the SSL/TLS Certificate:

  1. Navigate to Certificate Manager (ACM) in your management console.
  2. Click "Request a certificate".
  3. Enter a wildcard entry for your domain. For instance, my domain is aaronmedacco.com, so a "*.aaronmedacco.com" will cover any subdomain.
  4. Enter two more entries, one for both the www and non-www versions of your domain. For instance, "aaronmedacco.com" and "www.aaronmedacco.com", in my case.

    Certificate Manager 1
  5. Click "Review and request".
  6. Click "Confirm and request".
  7. Click "Continue".

The first couple times I did this, I only used the wildcard entry and of course, when I navigated to the non-www version of my domain, I received a certificate name mismatch screen in my browser. It never occurred to me to read the grey text underneath the big blue button staring me in the face.

Validating the SSL/TLS Certificate:

  1. You should be sent back to the dashboard page of Certificate Manager. You should see a status of "Pending validation" for your certificate.
  2. In order to activate the certificate, the domain owner will receive an email asking to verify the certificate request.

    Certificate Manager 2
  3. Click the link to approve the request.
  4. If you used more than one entry for the certificate and receive multiple emails, approve each of them.

Shortly after, the status should flip to "Issued". Now, we just need to add a listener to the Elastic Load Balancer. For this, I assume you've already created a load balancer listening for HTTP traffic on port 80.

Configuring the Elastic Load Balancer:

  1. Navigate to EC2 in your management console.
  2. Select "Load Balancers" in the sidebar.
  3. Select the load balancer distributing traffic to your web application.
  4. Click the "Listeners" tab.
  5. Click "Add listener".
  6. Select "HTTPS (Secure HTTP)" as the Protocol, 443 as the Port, and the appropriate target group.
  7. Choose to use an existing certificate from AWS Certificate Manager (ACM) and select the certificate you just created.
  8. Click "Create".

At this point, your load balancer will now listen for requests using HTTPS before relaying them to your application instances. One advantage to this configuration over managing SSL/TLS from the web servers, is that you offload that little bit of CPU. Your next step will likely entail configuring whichever web server you are using (IIS, Apache, etc.) to force the use of HTTPS for requests that are HTTP in nature.

Cheers!

Copyright © 2016-2017 Aaron Medacco