Origin cloaking
Overview
Origin cloaking is a set of techniques aiming at reducing the attack surface of web applications. It's a best practice to use CloudFront as a single-entry point to web applications, where security controls, such as protections against DDoS attacks and undesired bots, are applied. Origin cloaking stops malicious actors from by-passing CloudFront and its security controls to attack the origin directly, using firewall rules to block any traffic not coming from the CloudFront entry point. Origin cloaking can be achieved at multiple layers of the OSI model.
At network layer
When your origin allows you to control inbound network access, add restrictions to only allow traffic coming from CloudFront's network.
If you origin is an EC2 instance, an Application Load Balancer or a Network Load Balancer, you can keep your origin in a private subnet in your VPC, and leverage the VPC Origins feature of CloudFront. It allows you to restrict access exclusively to CloudFront distributions configured with VPC Origins in your own AWS account.
If have to leave such resources in a public subnet (e.g. your ALB will be accessed by multiple CDNs), or you have an origin type that is not supported by CloudFront's VPC Origins, you can restrict access to CloudFront using security groups. You need to associate your origin with a Security Group, to which you add the AWS-managed prefix list for Amazon CloudFront.
If your origin is on your premises, you can restrict access to CloudFront by allow listing CloudFront's origin facing IP addresses, which can be found in this IP list when you filter on the CLOUDFRONT_ORIGIN_FACING value of the service field. In this approach, you need to subscribe to IP changes to update your ACL. Check this blog post to learn how to implement origin cloaking on on-premise web servers using third-party firewalls. For further isolation from internet, consider setting up AWS Direct Connect between your on-prem infrastructure and AWS using a public virtual interfaces on the Direct Connect connection.
Access control at network layer is a starting point, but might not be enough for you. For example, if someone discovers the origin domain name on your premises, they can create a CloudFront distribution in their own AWS account and bypass your own distribution. Another example, is when you are using VPC Origin feature, you might want to restrict your origin to a specific CloudFront distribution in your AWS Account, compared to making it accessible to all CloudFront distributions configured with VPC Origins in your AWS Account. In this case, consider hardening with Application layer access control.
At application layer
Origin Access Control
Locking some types of origins to CloudFront is made very simple with Origin Access Control (OAC), a feature of CloudFront that signs requests to certain types of origins natively using AWS Signature Version 4 algorithm (sigv4) based on IAM policies. Today, OAC is compatible with S3, MediaStore, MediaPackage, and Lambda Function URLs and S3 Object Lambda. When OAC is used with S3, you can keep your S3 bucket private, with exclusive access to CloudFront based on S3 Bucket policies.
When the origin type is not supported by OAC, you can sign requests to your origin using edge functions. Example implementations are explained in the following blogs:
- Sign requests using Sigv4 with Lambda@Edge to AWS API Gateway
- Sign requests using MD5 with Lambda@Edge to NGINX servers
Access control based on shared secret key
If your origin does not support request signing, or you don't consider that this level of access control is needed for your application, then you can configure CloudFront to send a custom header containing a shared secret with your origin, that can be validated by your origin to process the request. Consider the following example implementation:
- ALB based origin. You can validate the secret header on an ALB based origin using an ALB rule or using an AWS WAF rule if your ALB is already associated with an AWS WAF WebACL.
- API Gateway based origin. You can validate the secret header on an API Gateway using API keys.
- NGINX based origin. Assuming that CloudFront sends a custom header X-CloudFront with value abc123, you can validate the secret header on Nginx based web server (Cloud based or On-premises based) by adding the following code in the server tag of the /etc/nginx/nginx.conf Nginx configuration file:
if ($http_x_cloudfront != "abc123") {
return 403;
} - Apache based origin. Assuming that CloudFront sends a custom header X-CloudFront with value abc123, you can validate the secret header on Apache based web server (Cloud based or On-premises based) by adding the following code in httpd.conf configuration file (and ssl.conf file if used):
RewriteEngine On
RewriteCond %{HTTP:x-cloudfront} !^abc123$ [NC]
RewriteRule ^ - [F]
In all cases, it's recommended to rotate this shared secret on a regular basis to reduce the risk of leaked secrets. In the sample implementations shared above, both the one with API Gateway and with ALB include an automation for secret rotation.