AWS WAFv2
AWS Web Access Firewall is one the services that can be used to inspect, control and manage web request.WAF uses one or many rules to allow, limit or block as per request statement provided within rule.AWS WAF and it's corresponding rule can be attached to multiple AWS services. such asOfficial AWS Link- Amazon CloudFront distribution,
- Amazon API Gateway REST API,
- Application Load Balancer,
- AWS API Gateway
In this blog post,, we will cover, how to restrict our AWS cloudfront distribution URL for limited IP Addresses only.
Lab Setup : So we have a Cloudfront distribution with both http and https access mapped to respective AWS S3 buckets, as we know once we have created a Cloudfront distribution, AWS provide us a publicly accessible Cloudfront domain URL, using which we can access our S3 content, thus url, which looks somehow similar to http://d3ocffr25e-somerandom.cloudfront.net
We will use AWS WAF to restrict/block access approaching to our Cloudfront domain to all random IP other than the one which we have whitelisted within our IP sets.
- Amazon CloudFront distribution,
- Amazon API Gateway REST API,
- Application Load Balancer,
- AWS API Gateway
In this blog post,, we will cover, how to restrict our AWS cloudfront distribution URL for limited IP Addresses only.
Lab Setup : So we have a Cloudfront distribution with both http and https access mapped to respective AWS S3 buckets, as we know once we have created a Cloudfront distribution, AWS provide us a publicly accessible Cloudfront domain URL, using which we can access our S3 content, thus url, which looks somehow similar to http://d3ocffr25e-somerandom.cloudfront.net
We will use AWS WAF to restrict/block access approaching to our Cloudfront domain to all random IP other than the one which we have whitelisted within our IP sets.
CloudFormation Template to create below resources.- IP Sets : AWS::WAFv2::IPSet
- Web ACLv2 : AWS::WAFv2::WebACL
- Custom Response Body : CustomResponseBodies
- Rules : IPSetReferenceStatement
- CloudWatch Metrics
- Sample Request Dashboard.
Note : After creation of below resources, this has to be associated with cloudformation distribution from cloudfromation section.
- IP Sets : AWS::WAFv2::IPSet
- Web ACLv2 : AWS::WAFv2::WebACL
- Custom Response Body : CustomResponseBodies
- Rules : IPSetReferenceStatement
- CloudWatch Metrics
- Sample Request Dashboard.
Syntax Template
---AWSTemplateFormatVersion: '2010-09-09'Description: This template will create WAFv2 Ipset, WebAcl with Cloudfront Scope, Web ACLs rules, Cloudwatch metric Sample Request Dashbaord with last 3 hour data.
Parameters: env: Description: The environment name being worked on Type: String AllowedValues: - prod - non-prod CloudFrontInfo: Description: Cloudfront Name. Type: String IPSetname: Description: The short name to identify ipsets. Type: String IPSetDescription: Description: Short description to identify ipsets. Type: String
Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Environment Parameters: - env - Label: default: IP Set Details Parameters: - IPSetname - IPSetDescription
Resources: SampleIPSet: Type: 'AWS::WAFv2::IPSet' Properties: Description: !Sub "${IPSetDescription}" Name: !Sub "${IPSetname}" Scope: CLOUDFRONT IPAddressVersion: IPV4 Addresses: - 111.11.11.11/32 # Random-Pub-IP-1 - 122.12.12.1/32 # Random-Pub-IP-2 - 133.225.192.0/18 # Random-Pub-IP-3
CDNAccessIPRestrictionWebACL: Type: AWS::WAFv2::WebACL Properties: Name: !Sub "myproject-${env}-cdn-${CloudFrontInfo}-WebACL" Scope: CLOUDFRONT DefaultAction: Block: { "CustomResponse": { "ResponseCode": 401, "CustomResponseBodyKey": "Unauthorized" } } Description: !Sub "To limit access of Cloudfront ${CloudFrontInfo} from known IP ranges only" Rules: - Name: !Sub "myproject-${env}-cdn-${CloudFrontInfo}-WebACL-Rule1" Priority: 0 Statement: IPSetReferenceStatement: Arn: !GetAtt SampleIPSet.Arn Action: Allow: {} VisibilityConfig: SampledRequestsEnabled: true CloudWatchMetricsEnabled: true MetricName: !Sub "myproject-${env}-cdn-${CloudFrontInfo}-IpLimitationRule" VisibilityConfig: SampledRequestsEnabled: true CloudWatchMetricsEnabled: true MetricName: !Sub "myproject-${env}-cdn-${CloudFrontInfo}-WebACLMetric" Capacity: 1
CustomResponseBodies: Unauthorized: ContentType: TEXT_PLAIN Content: Unauthorized !
Syntax Template
---AWSTemplateFormatVersion: '2010-09-09'Description: This template will create WAFv2 Ipset, WebAcl with Cloudfront Scope, Web ACLs rules, Cloudwatch metricSample Request Dashbaord with last 3 hour data.Parameters:env:Description: The environment name being worked onType: StringAllowedValues:- prod- non-prodCloudFrontInfo:Description: Cloudfront Name.Type: StringIPSetname:Description: The short name to identify ipsets.Type: StringIPSetDescription:Description: Short description to identify ipsets.Type: StringMetadata:AWS::CloudFormation::Interface:ParameterGroups:-Label:default: EnvironmentParameters:- env-Label:default: IP Set DetailsParameters:- IPSetname- IPSetDescriptionResources:SampleIPSet:Type: 'AWS::WAFv2::IPSet'Properties:Description: !Sub "${IPSetDescription}"Name: !Sub "${IPSetname}"Scope: CLOUDFRONTIPAddressVersion: IPV4Addresses:- 111.11.11.11/32 # Random-Pub-IP-1- 122.12.12.1/32 # Random-Pub-IP-2- 133.225.192.0/18 # Random-Pub-IP-3CDNAccessIPRestrictionWebACL:Type: AWS::WAFv2::WebACLProperties:Name: !Sub "myproject-${env}-cdn-${CloudFrontInfo}-WebACL"Scope: CLOUDFRONTDefaultAction:Block: {"CustomResponse": {"ResponseCode": 401,"CustomResponseBodyKey": "Unauthorized"}}Description: !Sub "To limit access of Cloudfront ${CloudFrontInfo} from known IP ranges only"Rules:- Name: !Sub "myproject-${env}-cdn-${CloudFrontInfo}-WebACL-Rule1"Priority: 0Statement:IPSetReferenceStatement:Arn: !GetAtt SampleIPSet.ArnAction:Allow: {}VisibilityConfig:SampledRequestsEnabled: trueCloudWatchMetricsEnabled: trueMetricName: !Sub "myproject-${env}-cdn-${CloudFrontInfo}-IpLimitationRule"VisibilityConfig:SampledRequestsEnabled: trueCloudWatchMetricsEnabled: trueMetricName: !Sub "myproject-${env}-cdn-${CloudFrontInfo}-WebACLMetric"Capacity: 1CustomResponseBodies:Unauthorized:ContentType: TEXT_PLAINContent: Unauthorized !
We will go through each sections of the CloudFormation template to understand the same.
Parameters : Follow the link to know more about it.
Going further into the Resource Section, our WAF relevant stuffs are defined.
AWS::WAFv2::IPSetThis part of CFN resource us used to define our custom set of IP Address, which will be later used while defining our WAF rules, Let's know what are those properties.
SampleIPSet: Type: 'AWS::WAFv2::IPSet' Properties: Description: !Sub "${IPSetDescription}" Name: !Sub "${IPSetname}" Scope: CLOUDFRONT IPAddressVersion: IPV4 Addresses: - 111.11.11.11/32 # Random-Pub-IP-1 - 122.12.12.1/32 # Random-Pub-IP-2 - 133.225.192.0/18 # Random-Pub-IP-3
Scope Scope can be either REGIONAL or CLOUDFRONT
As Cloudfront (CDN) is Global service, it's being treated as a Seperate scope.Note : Please note, this scope can be created only within us-east-1 region only.
SampleIPSet:
Type: 'AWS::WAFv2::IPSet'
Properties:
Description: !Sub "${IPSetDescription}"
Name: !Sub "${IPSetname}"
Scope: CLOUDFRONT
IPAddressVersion: IPV4
Addresses:
- 111.11.11.11/32 # Random-Pub-IP-1
- 122.12.12.1/32 # Random-Pub-IP-2
- 133.225.192.0/18 # Random-Pub-IP-3
Scope
Scope can be either REGIONAL or CLOUDFRONT
Addresses Used to define set of IP using the valid CIDR format.
Example : - 111.11.11.11/32 # Used to define single IP as /32
- 122.12.12.1/32
- 133.225.192.0/18 # Used to define entire subnet range as /18
Custom Response Body : CustomResponseBodies
Addresses
Used to define set of IP using the valid CIDR format.Example :- 111.11.11.11/32 # Used to define single IP as /32 - 122.12.12.1/32 - 133.225.192.0/18 # Used to define entire subnet range as /18
This part of CFN resource us used to define our custom response that can support in any type as ( Plain TEXT, HTML, JSON ), here we have used a plain text.
CustomResponseBodies:
Unauthorized:
ContentType: TEXT_PLAIN
Content: Unauthorized !
Rules
This part of WAF ACL CFN resource us used to custom rules (Allow, Deny )based upon statements.
- In our example, we are allowing IP Sets with priority 0 ( Highest Priority ), and it's linked the the ARN of the same IP Set, we have created above.
- In addition to that, we are creating Cloudwatch Metrics Dashboard for each Allowed Request.
- And at last we are enabling the Sampled Request, which will show us the Realtime calls/request.
Rules:
- Name: !Sub "myproject-${env}-cdn-${CloudFrontInfo}-WebACL-Rule1"
Priority: 0
Statement:
IPSetReferenceStatement:
Arn: !GetAtt SampleIPSet.Arn
Action:
Allow: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: !Sub "myproject-${env}-cdn-${CloudFrontInfo}-IpLimitationRule"
Web ACLv2 : AWS::WAFv2::WebACLThis part of CFN resource us used to define the WAFv2 ACl and it defines the below parts.- It has scope of CloudFront.
- Default action is to Block everything and thus in response provide HTTP access code 401 and with the custom response body that we have created above part.
- It will create a Cloudwatch metric dashboard for all blocked request.
- It will also create a panel for all realtime blocked request/calls.
CDNAccessIPRestrictionWebACL: Type: AWS::WAFv2::WebACL Properties: Name: !Sub "myproject-${env}-cdn-${CloudFrontInfo}-WebACL" Scope: CLOUDFRONT DefaultAction: Block: { "CustomResponse": { "ResponseCode": 401, "CustomResponseBodyKey": "Unauthorized" } } Description: !Sub "To limit access of Cloudfront ${CloudFrontInfo} from known IP ranges only" Rules: - Name: !Sub "myproject-${env}-cdn-${CloudFrontInfo}-WebACL-Rule1" Priority: 0 Statement: IPSetReferenceStatement: Arn: !GetAtt SampleIPSet.Arn Action: Allow: {} VisibilityConfig: SampledRequestsEnabled: true CloudWatchMetricsEnabled: true MetricName: !Sub "myproject-${env}-cdn-${CloudFrontInfo}-IpLimitationRule" VisibilityConfig: SampledRequestsEnabled: true CloudWatchMetricsEnabled: true MetricName: !Sub "myproject-${env}-cdn-${CloudFrontInfo}-WebACLMetric" Capacity: 1
- This part creates the AWS WAFv2 w
Web ACLv2 : AWS::WAFv2::WebACL
This part of CFN resource us used to define the WAFv2 ACl and it defines the below parts.
- It has scope of CloudFront.
- Default action is to Block everything and thus in response provide HTTP access code 401 and with the custom response body that we have created above part.
- It will create a Cloudwatch metric dashboard for all blocked request.
- It will also create a panel for all realtime blocked request/calls.
CDNAccessIPRestrictionWebACL:
Type: AWS::WAFv2::WebACL
Properties:
Name: !Sub "myproject-${env}-cdn-${CloudFrontInfo}-WebACL"
Scope: CLOUDFRONT
DefaultAction:
Block: {
"CustomResponse": {
"ResponseCode": 401,
"CustomResponseBodyKey": "Unauthorized"
}
}
Description: !Sub "To limit access of Cloudfront ${CloudFrontInfo} from known IP ranges only"
Rules:
- Name: !Sub "myproject-${env}-cdn-${CloudFrontInfo}-WebACL-Rule1"
Priority: 0
Statement:
IPSetReferenceStatement:
Arn: !GetAtt SampleIPSet.Arn
Action:
Allow: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: !Sub "myproject-${env}-cdn-${CloudFrontInfo}-IpLimitationRule"
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: !Sub "myproject-${env}-cdn-${CloudFrontInfo}-WebACLMetric"
Capacity: 1
- This part creates the AWS WAFv2 w