Amazon CloudFront and Security Groups
Some background info
AWS has recently released some features that drastically simplify how we can secure network traffic to a VPC based CloudFront Origin. Before I get to that however, let's refresh on a few things quickly at a super high level.
- Amazon CloudFront is a global content delivery network (CDN) that helps you get your content as close to the end user as possible, reducing latency and response times while caching data to reduce the load on your servers
- Amazon Virtual Private Cloud is the virtual network construct within AWS, this is where you manage and configure networking for your resources
- A Security Group acts as a virtual firewall for your EC2 Instance allowing you to control inbound and outbound traffic
The most basic architecture we can have would look something like this, I've left out quite a few components from the diagram like regions and availability zones so we can keep this simple:
The client accesses a website hosted by the web server. We have also configured CloudFront in front of our web server to reduce the load on our server by caching our content.
CloudFront is a public internet facing service, this means that it needs to connect to our Web Server on a Public IP address. Our Security Group for our Web Server in this example looks something like this:
As you can see here we have allowed HTTP and HTTPS to our web server from anywhere (0.0.0/0).
If we don’t secure this somehow, if someone was to figure out the public IP to our web server, they would be able to go directly to the server and bypass CloudFront, like this:
This can have a bunch of consequences, ranging from security all the way to performance and unintended cost because you're not getting the benefits of CloudFront.
Now the problem we have is CloudFront is a Global Service, meaning that when the traffic comes from CloudFront to your web server, it can come from different servers all over the world, all with different IPs. These IP addresses also change all of the time as AWS scales and operates the service.
So how do we update our security group so we are only allowing traffic from CloudFront but also keeping it up to date with all of the IP ranges that AWS use for this service, clearly doing this manually would be impossible.
The new solution
Until recently, one solution to this was using an AWS Lambda function (a service that lets you run code without servers), this function would go get the IP ranges that AWS publish and then update the security groups (you can read a blog post on this from Amazon here).
While this solution worked well, it’s a bit complicated and requires a few moving parts.
Luckily AWS has released two new features to help us with this:
- The first one being Prefix lists, this allows us to create a managed list of IP address ranges for use in the source field of a security groups
- And the second feature being an AWS-managed prefix list for CloudFront (there is also one for S3 and DynamoDB too)
This allows us to use a prefix list in our security group that is managed by AWS and contains all of the CloudFront IP ranges, the best thing is that this list requires nothing from us to keep it up to date.
Using an AWS-managed prefix list is super simple:
- Edit your Security Group
- Delete your HTTP and HTTPs rules (you unfortunately can’t edit a rule when using a prefix list otherwise you will get the error “You may not specify a prefix list for an existing IPv4 CIDR rule.”)
- Create your new HTTP and HTTPS rules and set the source to com.amazonaws.global.cloudfront.origin-facing
Now here is where you might get the error “The maximum number of rules per security group has been reached.”
The default quota for security groups is 60 rules and the CloudFront prefix list currently contains 55 rules. So, if you try and add the AWS-managed prefix list for both HTTP and HTTPS you will get this error if you haven’t asked for a quota increase (you can find more details on this here)
To show a end result however, here is the security group updated to use the AWS-managed prefix list for HTTPS:
Now that’s it, if you have been using the Lambda solution, you can now up your stacks to use the AWS-managed prefix list and if you didn’t know you needed to do this, you now have a simple easy to implement solution. Also, because this is a security group, you can also use it for things like Elastic Load Balancers too.