AWS WAFのレートベースルールでDDoSを緩和する

AWS WAFのレートベースルールでDDoSを緩和する

AWS WAFは、SQLインジェクションやXSSといったレイヤー7攻撃に対する保護を提供します。加えて、レートベースルールを使ってDDoS攻撃を緩和することもできます。

Takahiro Iwasa
6 min read

AWS WAFは、SQLインジェクションやXSSといったレイヤー7攻撃に対する保護を提供します。加えて、レートベースルールを使ってDDoS攻撃を緩和することもできます。

🔥 Caution

AWS WAFのレートベースルールはDDoS攻撃の緩和に役立ちますが、完全な保護を提供するものではありません。より包括的な保護が必要な場合は、AWS Shield Advancedの利用を検討してください。

考慮事項:

  • 設定できる最小レートは100です。
  • AWS WAFは30秒ごとにリクエストのレートをチェックし、その都度直近5分間のリクエストをカウントします。そのため、AWS WAFがトラフィックを検知して制限するまでに最大30秒かかる場合があります。
  • AWS WAFのレート制限には10,000のIPアドレスという上限があります。10,000を超えるアドレスがレートを超過した場合、AWS WAFは最もレートの高いものから制限します。

構築

以下のテンプレートはレート制限100を設定します。

AWSTemplateFormatVersion: 2010-09-09
Description: AWS WAF Rate-based rule sample
Resources:
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

スタックをデプロイします。

Terminal window
aws cloudformation deploy \
--region us-east-1 \
--stack-name aws-waf-rate-based-rule-sample \
--template-file template.yaml
Important

Scope: CLOUDFRONTを含むAWS WAFv2 Web ACLルールは、us-east-1リージョンにデプロイする必要があります。

サンプルのindex.htmlをS3バケットにアップロードします。

Terminal window
echo '<html><body>Hello World!</body></html>' > index.html
aws s3 cp index.html s3://aws-waf-rate-based-rule-sample-<ACCOUNT_ID>-us-east-1

テスト

AWS WAFのレートチェック間隔は30秒であるため、130秒以上にわたって1秒ごとにリクエストを送信します。設定したレート制限を超えたリクエストは、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.

Terminal window
for i in `seq 1 130`; do
echo "Request: $i"
curl https://<CLOUDFRONT_DOMAIN>/
echo "\n"
sleep 1
done

ブロックされたレスポンスの例。

<!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>

クリーンアップ

この例でプロビジョニングしたリソースを以下のコマンドで削除します。

Terminal window
aws s3 rm --recursive s3://aws-waf-rate-based-rule-sample-<ACCOUNT_ID>-us-east-1
aws cloudformation delete-stack \
--region us-east-1 \
--stack-name aws-waf-rate-based-rule-sample

まとめ

CloudFrontディストリビューションを、上限100リクエストのWAFレートベースルールの背後に配置してデプロイしたところ、閾値を超えたトラフィックが403レスポンスでブロックされることがわかりました。このルールをテストする際に最も混乱しやすいのが、30秒の評価ウィンドウです。制限を大きく超えるバーストトラフィックでも、最初の30秒ほどは通過してしまうことがあり、これは一見するとルールが機能していないように見えますが、実際には単に独自のスケジュールで評価されているだけです。この組み込みの遅延と、レート制限における10,000IPという上限が、冒頭の注意書きでこれをDDoS防止ではなくDDoS緩和と位置づけている理由です。単一の送信元がエンドポイントを叩き続けるようなケースを抑える以上の対策が必要な場合、このルールはAWS Shield Advancedを補完するものであり、その代替にはなりません。

About the author

Takahiro Iwasa

Takahiro Iwasa

Software Developer

This blog shares technical notes from hands-on projects—architecture, implementation, and AWS service integrations.