If you use CloudFront as your front door, why leave your ALB side door unlocked and opened for anyone to walk through?


TLDR

  • With about 10 minutes of work, you can ensure inbound traffic is only sent to your app through CloudFront
  • The improved security is accomplished by ensuring HTTP headers in requests through the ALB match what would ideally only be set at CloudFront
  • You can improve security further by ensuring you don’t use public IPs for your EC2 instances or by only allowing traffic from the ALB.

Introduction

CloudFront is your application’s front door. It’s where you do your caching, security, and initial monitoring of your user’s interactions. It is widely available, with over 450 points of presence as of February 2023, and, most importantly, it’s fast.

Given the above, ensuring your customers interact with your app through CloudFront is essential. Afraid of a possible distributed denial of service attack? CloudFront with WAF & Shield is a great place to start. Have a lot of static assets and want to reduce the load on your origin? Setup up an aggressive caching policy.


What Is Origin Security and Why Should You Care?

With the benefits of CloudFront, you should ensure users can only use CloudFront and not directly contact your ALB or compute (EC2, ECS, etc.) behind the load balancer. Ensuring users can only access your application through CloudFront makes it much easier to secure your application.

Some methods of securing your origin include using a WAF, TLS, and preventing direct access to your application servers.

In this particular write-up, I will explain how to configure CloudFront, your ALB, and your instances to ensure a highly secured environment.

The architecture I’m working with in this example

How To Configure Origin Security to Your ALB

This write-up assumes that you have the following already:

  • A CloudFront distribution
  • An application load balancer
  • An active target for the ALB
     — I’m using an EC2 instance in an auto-scaling group, but it can be any valid target.

CloudFront

Starting with CloudFront, you will add a custom header forwarded to the origin, the ALB in this case. From the CloudFront service page:

  1. Click on the distribution you want to secure.
  2. Navigate to the Origins tab.
  3. Select and edit the origin.
  4. Scroll down to “Add custom header” and add a new header with your choice of header name and value.
     — Make sure this is secure, as this is part of the security that prevents users from accessing your app outside the CloudFront distribution.
0:00
/0:21

ALB

Next, in the ALB configuration, you will start at the load balancer’s listener configuration. The key is to have a rule looking for the header you just added to the CloudFront distribution and then set the default rule to return a fixed response (or send it somewhere else).

  1. Select the listener you want to secure.
  2. Navigate to the defined rules for the selected listener.
  3. Click on the rule configuration.
  4. Add a new rule with a condition matching on HTTP header:
     — This should match the header name and value you previously set in the CloudFront distribution.
  5. Forward the new rule to your target group for your backend.
  6. Edit the default or last rule to return a fixed response or send it to a static page with a redirect action.
     — I chose an HTTP 401 with the string “Unauthorized”.
0:00
/0:57

EC2

This step isn’t required, but it’s a good practice if you have public IP addresses assigned to your EC2 instances. You will want to edit your security groups for the EC2 instances only to allow traffic from your ALB security group.

  1. Select your EC2 instance’s security group.
  2. Edit the inbound rules.
  3. Remove any undesired and unrestricted inbound rules.
  4. Add an inbound rule with a custom source, which should be the security group attached to your ALB.

Closing Thoughts

As you can see, having that much more secure posture for your application is a simple process.

This is far from a perfect solution, as there is no way to set the value of the headers so that it is entirely secret. It will be known when being set or when the CloudFront distribution or ALB is viewed.

Infrastructure as Code tools like Terraform or CloudFormation can mostly fix this issue with random secret generation and the support of multiple values, allowing for a seamless value rotation.

On top of the above changes to the CloudFront distribution and ALB, you should be sure that CloudFront is sending only HTTPS traffic to the origin, which you can do by editing the protocol in the origin settings in the settings for the distributions.


References