Mitigating DDoS with AWS WAF Rate-Based Rules
AWS WAF provides protection against layer 7 attacks such as SQL injection and XSS. In addition, you can use rate-based rules to mitigate DDoS attacks.
AWS WAF provides protection against layer 7 attacks such as SQL injection and XSS. In addition, you can use rate-based rules to mitigate DDoS attacks.
AWS WAF rate-based rules can help mitigate DDoS attacks, but they cannot provide complete protection. For more comprehensive protection, consider using AWS Shield Advanced.

Considerations:
- The minimum rate that you can set is 100.
- AWS WAF checks the rate of requests every 30 seconds, and counts requests for the prior 5 minutes each time. Therefore, it may take up to 30 seconds for AWS WAF to detect and restrict the traffic.
- AWS WAF has a limit of 10,000 IP addresses for rate limiting. When more than 10,000 addresses exceed the rate, AWS WAF restricts those with the highest rates.
Building
Create a CloudFormation template with the following content. In this note, a rate limit of 100 is configured.
AWSTemplateFormatVersion: 2010-09-09Description: AWS WAF Rate-based rule sampleResources: S3Bucket: Type: AWS::S3::Bucket Properties: BucketName: !Sub aws-waf-rate-based-rule-sample-${AWS::AccountId}-${AWS::Region} BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: AES256 PublicAccessBlockConfiguration: BlockPublicAcls: TRUE BlockPublicPolicy: TRUE IgnorePublicAcls: TRUE RestrictPublicBuckets: TRUE
S3BucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref S3Bucket PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: cloudfront.amazonaws.com Action: s3:GetObject Resource: !Sub arn:aws:s3:::${S3Bucket}/* Condition: StringEquals: "AWS:SourceArn": !Sub arn:aws:cloudfront::${AWS::AccountId}:distribution/${CloudFrontDistribution}
# AWS::WAFv2::WebACL must be deployed in us-east-1. WAFv2WebACL: Type: AWS::WAFv2::WebACL Properties: Name: aws-waf-rate-based-rule-sample DefaultAction: Allow: { } VisibilityConfig: SampledRequestsEnabled: true CloudWatchMetricsEnabled: true MetricName: aws-waf-rate-based-rule-sample Scope: CLOUDFRONT Rules: - Name: rate-based-rule Priority: 0 Action: Block: { } Statement: RateBasedStatement: Limit: 100 AggregateKeyType: IP VisibilityConfig: SampledRequestsEnabled: true CloudWatchMetricsEnabled: true MetricName: rate-based-rule
CloudFrontOriginAccessControl: Type: AWS::CloudFront::OriginAccessControl Properties: OriginAccessControlConfig: Name: aws-waf-rate-based-rule-sample OriginAccessControlOriginType: s3 SigningBehavior: always SigningProtocol: sigv4
CloudFrontDistribution: Type: AWS::CloudFront::Distribution DependsOn: CloudFrontOriginAccessControl Properties: DistributionConfig: Origins: - Id: !GetAtt S3Bucket.DomainName DomainName: !GetAtt S3Bucket.DomainName OriginAccessControlId: !Ref CloudFrontOriginAccessControl S3OriginConfig: OriginAccessIdentity: '' DefaultCacheBehavior: CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6 TargetOriginId: !GetAtt S3Bucket.DomainName ViewerProtocolPolicy: allow-all Enabled: true ViewerCertificate: CloudFrontDefaultCertificate: true MinimumProtocolVersion: TLSv1 WebACLId: !GetAtt WAFv2WebACL.Arn DefaultRootObject: index.htmlDeploy the CloudFormation stack with the following command:
aws cloudformation deploy \ --region us-east-1 \ --stack-name aws-waf-rate-based-rule-sample \ --template-file template.yaml
AWS WAFv2 web ACL rules containing Scope: CLOUDFRONT must be deployed in the us-east-1 region.
Upload a sample index.html to the S3 bucket:
echo '<html><body>Hello World!</body></html>' > index.htmlaws s3 cp index.html s3://aws-waf-rate-based-rule-sample-<ACCOUNT_ID>-us-east-1Testing
Since the AWS WAF rate-checking interval is 30 seconds, send requests every second for 130 seconds or longer. Requests exceeding the configured limit will be blocked with a 403 Forbidden response.
https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-rate-based.html
AWS WAF checks the rate of requests every 30 seconds, and counts requests for the prior five minutes each time.
for i in `seq 1 130`; do echo "Request: $i" curl https://<CLOUDFRONT_DOMAIN>/ echo "\n" sleep 1doneExample blocked response:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"><TITLE>ERROR: The request could not be satisfied</TITLE></HEAD><BODY><H1>403 ERROR</H1><H2>The request could not be satisfied.</H2><HR noshade size="1px">Request blocked.We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.<BR clear="all">If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.<BR clear="all"><HR noshade size="1px"><PRE>Generated by cloudfront (CloudFront)Request ID: xxxxxxxxxxxxxxxxxxxx</PRE><ADDRESS></ADDRESS></BODY></HTML>Cleaning Up
Clean up all the AWS resources provisioned during this example with the following command:
aws s3 rm --recursive s3://aws-waf-rate-based-rule-sample-<ACCOUNT_ID>-us-east-1aws cloudformation delete-stack \ --region us-east-1 \ --stack-name aws-waf-rate-based-rule-sampleRelated posts
Sign in with Slack Using Cognito User Pools and OIDC
This note describes how to federate Cognito user pools with Slack using OIDC to implement "Sign in with Slack".
Deploying FastAPI on AWS Lambda with Lambda Web Adapter
This example guides you through the process of developing API backends with FastAPI using Lambda Web Adapter.
API Gateway WebSocket: Implementing a Mock Integration
This note describes how to build an API Gateway WebSocket endpoint using mock integration.
Uploading to S3 Through CloudFront Pre-Signed URLs
CloudFront signed URLs let you upload to S3 through a custom domain—useful when direct S3 pre-signed URLs are not an option.
AWS EventBridge Scheduler: Automate EC2 Scheduling with Ease
This note describes how to automate starting and stopping of EC2 instances using EventBridge Scheduler.
