Recently working on the client project where we need to protect the public facing ALB with the Web Application Firewall. After the internal discussion, we feel that WAF protection at the ALB level is too late or in other word too close to the client resources, we need something outside the client VPC or at the edge location.
The only architecture that we can come out is fronting the public ALB with CloudFront, and bind the WAF to the CloudFront, by that, the protection actually happen at the edge location where the CloudFront exists.
The following diagram is the initial architecture before we implement the CloudFront or WAF, the public facing ALB actually open the port 443 to the 0.0.0.0/0, which mean anyone can visit the site without any restriction including the bad bot.
After we enhance the architecture by adding the CloudFront + WAF in front of the public ALB and restrict the Public ALB security group to only accept request from CloudFront IP list. Now the public domain name (www.example.com) being point to the CloudFront domain name instead of the ALB, and the origin of the CloudFront actually point to the default ALB domain name, everything is working perfectly. But there is an issue where the connectivity between CloudFront to ALB is unencrypted, because we can’t bind the SSL from ACM to the ALB if using the default domain name from AWS.
This is a very common used case and it’s work perfectly for most of the organization who don’t require end to end encryption of their traffic, but for some regulated industry, this is unacceptable.
So to resolved the end-to-end encryption issue, the follow is our final and complete architecture design. We actually create another DNS CName record (origin.example.com) and point it to the ALB default domain name, with the origin.example.com, now we can bind the SSL certificate to the ALB and achieve the end to end encryption for the network traffic.
In this post, I just focus on the domain name issue that I face during designing the architecture, but there are few more important consideration need to be in place, for example the security group should be lock down to only listening to port 443 from CloudFront IP list, AWS provide a simple solution on this by whitelist the CloudFront AWS Managed Prefix List (Previously need to be done by using SNS + Lambda to update the SG).
Another pro tips for the solution above is using the ACM (AWS Certificate Manager) provided by the AWS, you will get free certificate with auto renewal in place as long as you bind the certificate to any of the supported AWS services (ex: NLB, CloudFront).