Networking & Content Delivery

Limit access to your origins using the AWS-managed prefix list for Amazon CloudFront

Amazon CloudFront provides an easy and cost-effective way to distribute content with low latency and high data transfer speeds using a worldwide network of edge locations. To enable requests from CloudFront to access your origins (the source of your content, for example, Amazon Elastic Compute Cloud (Amazon EC2) instances, the security policies on your origin must allow access from all of the IP ranges belonging to CloudFront. AWS publishes the current IP addresses including CloudFront in JSON format, and these IP ranges can change frequently. Therefore, it can become tedious to constantly update the allowed IP ranges in your security groups manually. To avoid this, you might consider opening inbound access on your origins to all of the IP addresses. However, this isn’t recommended under the AWS Best Practices for DDoS Resiliency. If you leave your origins open to all of the IP addresses, then an adversary can launch attacks directly on your origin resources, thus bypassing the protections provided by CloudFront and deployed on CloudFront.

Some workarounds have been built to restrict access to your origin from CloudFront by only automating the process of updating your security groups when the CloudFront IP ranges change, such as this solution using . This involves additional configuration and the cost of running Lambda functions. To simplify this, we have now introduced an AWS-managed prefix list for CloudFront to limit the inbound HTTP/HTTPS traffic to your origins from only the CloudFront origin-facing IP addresses. AWS-managed prefix lists are created and maintained by AWS and are available to use at no additional cost. You can reference the managed prefix list for CloudFront in your (Amazon VPC) security group rules, subnet route tables, common security group rules with AWS Firewall Manager, and any other AWS resources that can use a managed prefix list.

Using managed prefix list in a security group

You can use the managed prefix list for CloudFront as a part of your inbound rules in security groups that you attach to your origin resources, such as your EC2 instances or Application Load Balancers.

Note that the managed prefix list for CloudFront counts as 55 rules in a security group. The default quota for security groups is 60 rules, leaving room for only 5 additional rules if you add one managed prefix list for CloudFront in your Inbound rules. If you want to limit both HTTP and HTTPS requests using the managed prefix list for CloudFront, then you must add two separate rules, which will count as 110 total rules. You can request a quota increase for this quota if you need it. Alternately, you can open only one inbound port, preferably HTTPS, by configuring the CloudFront origin protocol policy to use only HTTPS to access your origin.

To add a managed prefix list for CloudFront using the AWS console, navigate to the Security Groups section under VPC in the AWS region where you have your origin resources that will use this security group.

You can create a new security group or update an existing one. On the Inbound rules section, select the Type as HTTP or HTTPS as per your requirements, and for the Source search for a prefix list that includes the string global.cloudfront.origin-facing. The prefix list ID varies by AWS region, so your ID may look different from what is shown in the following screenshot

Screenshot of security group rules

You can find the Prefix list ID value for your AWS region from the Amazon VPC console. In the Managed Prefix Lists section, look for an entry with Prefix list name com.amazonaws.global.cloudfront.origin-facing. The following screenshot shows a value of pl-31a34658 for the Singapore region.

Screenshot of managed prefix lists

Furthermore, you can look up the prefix list ID for your AWS region using AWS Command Line Interface (AWS CLI) by running the following command:

aws ec2 describe-managed-prefix-lists --query 'PrefixLists[?PrefixListName==`com.amazonaws.global.cloudfront.origin-facing`]' --region <insert region name>

Screenshot of command in terminal to query prefix lists

If you prefer to create your security group using AWS CloudFormation, you can use this sample template and edit it as per your requirements to include the CloudFront managed prefix list:

# /*
# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# *
# * Change History:
# * 2022-02-09: Created. Supported in all regions except Jakarta (ap-southeast-3), Osaka (ap-northeast-3), # * China and GovCloud regions
# */

AWSTemplateFormatVersion: 2010-09-09
Description: |
  CloudFront HTTPS ingress only SG via managed prefix list
  (https://aws.amazon.com/about-aws/whats-new/2022/02/amazon-cloudfront-managed-prefix-list/).
  Prefix list may not be supported for some regions
  (Run aws ec2 describe-managed-prefix-lists to verify presence of "com.amazonaws.global.cloudfront.origin-facing" PrefixListName)

Parameters:
  securityGroupName:
    Type: String
    Description: Security Group Name
    Default: CloudFront ingress only
  vpcID:
    Type: AWS::EC2::VPC::Id
    Description: VPC

Mappings:
  # aws ec2 describe-managed-prefix-lists  --region <REGION> | jq -r '.PrefixLists[] | select (.PrefixListName == "com.amazonaws.global.cloudfront.origin-facing") | .PrefixListId'
  AWSRegions2PrefixListID:
    ap-northeast-1:
      PrefixList: pl-58a04531
    ap-northeast-2:
      PrefixList: pl-22a6434b
    #ap-northeast-3
    #
    ap-south-1:
      PrefixList: pl-9aa247f3
    ap-southeast-1:
      PrefixList: pl-31a34658
    ap-southeast-2:
      PrefixList: pl-b8a742d1
    #ap-southeast-3:
    #  PrefixList:
    ca-central-1:
      PrefixList: pl-38a64351
    eu-central-1:
      PrefixList: pl-a3a144ca
    eu-north-1:
      PrefixList: pl-fab65393
    eu-west-1:
      PrefixList: pl-4fa04526
    eu-west-2:
      PrefixList: pl-93a247fa
    eu-west-3:
      PrefixList: pl-75b1541c
    sa-east-1:
      PrefixList: pl-5da64334
    us-east-1:
      PrefixList: pl-3b927c52
    us-east-2:
      PrefixList: pl-b6a144df
    us-west-1:
      PrefixList: pl-4ea04527
    us-west-2:
      PrefixList: pl-82a045eb
Resources:
  securityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Ref securityGroupName
      GroupDescription: Only allow CloudFront ingress
      VpcId: !Ref vpcID
      SecurityGroupEgress:
        - Description: Allow all outbound traffic
          IpProtocol: "-1"
          CidrIp: 0.0.0.0/0
      SecurityGroupIngress:
        - Description: Allow HTTPS from com.amazonaws.global.cloudfront.origin-facing
          IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          SourcePrefixListId:  !FindInMap [AWSRegions2PrefixListID, !Ref 'AWS::Region', PrefixList]
      Tags:
        - Key: StackName
          Value: !Sub ${AWS::StackName}
        - Key: StackId
          Value: !Sub ${AWS::StackId}
        - Key: Name
          Value: !Ref securityGroupName
Outputs:
  SecurityGroup:
    Value: !Sub "https://console.aws.amazon.com/ec2/home?region=${AWS::Region}#SecurityGroups:search=${securityGroup}"

Using the managed prefix list in a VPC route table

You can use the managed prefix list for CloudFront in your VPC route table. For example, this can be done to block all other outgoing internet traffic from a CloudFront origin resource.

The managed prefix list for CloudFront counts as 55 routes in a route table. The default quota is 50 routes, so you must request a quota increase before you can add the prefix list to a route table.

To add a managed prefix list for CloudFront using the AWS console, navigate to the Route Tables section under VPC in the AWS region where you have your VPC that will use this route table.

You can create a new route table, or edit routes in an existing table. On the Edit routes section, select Add route. For the Destination, select the prefix list that includes the string global.cloudfront.origin-facing from the dropdown list. For the target, select an Internet Gateway where you want these routing rules to be applied, and then save changes.

Screenshot of VPC routes table

Using the managed prefix list with AWS Firewall Manager

 You can use AWS Firewall Manager to centrally control the automatic association of security groups to multiple accounts and resources across your Organization. For example, you can define a common security group policy that includes a security group with inbound access allowed only from the managed prefix for CloudFront. Then, Firewall Manager can automatically apply this security group to Application Load Balancers and EC2 instances of your choice across multiple AWS accounts.

To create this using the AWS console, navigate to Firewall Manager in your administrator account. Create a new security group following the same steps as described in the Using managed prefix list in security group section earlier in this post. Go to Security policies and create a new policy. Under the Policy rules section, select the security group that you just created and add to the policy. In Policy action, you can choose to either auto-remediate any non-compliant resources which will apply the new security policy to all of your resources covered by Firewall Manager, or you can choose to just identify the non-compliant resources and update them manually.

Screenshot of Firewall Manager policy creation

You can define the Firewall Manager policy scope to apply this security group across your Application Load Balancers, Classic Load Balancers, EC2 instances, and Elastic Network Interfaces to limit inbound access on all of them to CloudFront origin-facing IP ranges only.

Conclusion

You have learned how to use the CloudFront managed prefix list to limit access to your origins to traffic coming only from CloudFront. The managed prefix list is available for immediate use via the AWS Console, as well as the AWS SDK in all regions except GovCloud, China, Asia Pacific (Jakarta), and Asia Pacific (Osaka).

You may have noticed that the managed prefix list for CloudFront contains fewer prefixes as compared to the over one hundred prefixes documented in Locations and IP address ranges of CloudFront edge servers. This is because the prefix list is a subset that includes AWS origin facing servers from CloudFront’s edge and regional locations. You can filter the prefixes from ip-ranges.json with the service code values CLOUDFRONT_ORIGIN_FACING and CLOUDFRONT respectively.

This AWS-managed prefix list provides protection at the network layer, and it’s just one part of your overall infrastructure and data security strategy. In addition, you should implement other ways for CloudFront to help you make sure of security in the cloud. Moreover, you can consider using AWS WAF for defense in-depth at the application layer, as well as using AWS Network Firewall and Amazon GuardDuty to block suspicious traffic as a part of your comprehensive security measures. To manage access at scale across the entire organization, you can use Firewall Manager. Refer to these Security posts on Firewall Manager to learn more.

Karan Desai author headshot

Karan Desai

Karan Desai is a Solutions Architect at AWS in India. He has over eleven years of cloud industry experience, with a focus on edge technologies and networking. He currently works with small businesses, designing scalable cost-efficient solutions that empower them to modernize and grow using the AWS cloud.

Lim Mike Author

Mike Lim

Mike Lim is a Solutions Architect based in Singapore where he helps customers achieve their business goals with AWS cloud services. He is a technology geek who enjoys finding innovative solutions to solve challenges. You can find him contributing to the community on GitHub at @limmike.