AWS WAF のレートベースルールで DDoS を緩和する
AWS WAF のレートベースルールで過剰なリクエストを制限し、アプリケーションレイヤーの DDoS 攻撃を緩和します。
AWS WAF は、SQL インジェクションやクロスサイトスクリプティング(XSS)などのレイヤー 7 攻撃から Web アプリケーションを保護します。レートベースルールを使うと、過剰なリクエストを制限し、アプリケーションレイヤーの DDoS 攻撃を緩和できます。
AWS WAF のレートベースルールは DDoS 攻撃の緩和に役立ちますが、完全な保護を提供するものではありません。より包括的な保護が必要な場合は、AWS Shield Advanced の利用を検討してください。

2023 年 1 月時点の動作と制限は、次のとおりです。
- 設定できる最小レートは、追跡対象の IP アドレスごとに5 分間で 100 リクエストです。
- AWS WAF は30 秒ごとにリクエストレートを確認し、その都度直近 5 分間のリクエストを集計します。そのため、トラフィックを検知して制限するまでに最大 30 秒かかる場合があります。
- AWS WAF のレート制限で追跡できる IP アドレスは 10,000 個までです。10,000 個を超えるアドレスがレートを超過した場合、リクエストレートが最も高いものから制限します。
構築
以下のテンプレートでは、送信元 IP アドレスごとに5 分間で 100 リクエストのレート制限を設定します。
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.htmlスタックをデプロイします。
aws cloudformation deploy \ --region us-east-1 \ --stack-name aws-waf-rate-based-rule-sample \ --template-file template.yaml
Scope: CLOUDFRONT を含む AWS WAFv2 Web ACL ルールは、us-east-1 リージョンにデプロイする必要があります。
サンプルの index.html を S3 バケットにアップロードします。
echo '<html><body>Hello World!</body></html>' > index.htmlaws s3 cp index.html s3://aws-waf-rate-based-rule-sample-<ACCOUNT_ID>-us-east-1テスト
AWS WAF は 30 秒ごとにリクエストレートを評価するため、1 秒に 1 回のリクエストを 130 秒以上送信します。設定した上限を超えた状態が評価されると、以後のリクエストは 403 Forbidden レスポンスでブロックされます。
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 1doneブロックされたレスポンスの例。
<!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>クリーンアップ
この例でプロビジョニングしたリソースを以下のコマンドで削除します。
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-sampleまとめ
送信元 IP アドレスが 5 分間で 100 リクエストという上限を超えると、WAF のレートベースルールが CloudFront ディストリビューションへのリクエストを 403 レスポンスでブロックします。
テスト時に注意したいのが、30 秒の評価間隔です。直近 5 分間のリクエスト数が上限を超えた後も、AWS WAF が次に評価するまではリクエストが通過する場合があります。
評価の遅延と 10,000 IP という追跡上限があるため、これは完全な DDoS 防御ではなく緩和策です。レートベースルールは AWS Shield Advanced などを補完するものであり、その代替にはなりません。
Related posts
Cognito User Pools と OIDC で Slack サインインを実装する
Cognito user pool を OIDC 経由で Slack と連携させ、"Sign in with Slack" を Amplify で Next.js アプリケーションに組み込みます。
Lambda Web Adapter で FastAPI を AWS Lambda にデプロイする
FastAPI で書いた API バックエンドをコンテナ化し、Lambda Web Adapter と AWS CDK を使って単一の Lambda 関数へデプロイします。
API Gateway WebSocket:モック統合の実装
バックエンドの Lambda を使わず、モック統合のみで API Gateway WebSocket API を構築し、あらかじめ用意したレスポンスを返します。
CloudFront 署名付き URL 経由で S3 にアップロードする
CloudFront の署名付き URL を使い、独自ドメイン経由で S3 にアップロードする方法を紹介します。S3 の署名付き URL を直接使えない場合に有用です。
AWS EventBridge Scheduler:スケジュールに沿って EC2 を起動・停止する
Lambda を介さず、EventBridge Scheduler から EC2 API を直接呼び出し、cron スケジュールに従って EC2 インスタンスを起動・停止します。
