AWS WAFのレートベースルールでDDoSを緩和する
AWS WAFは、SQLインジェクションやXSSといったレイヤー7攻撃に対する保護を提供します。加えて、レートベースルールを使ってDDoS攻撃を緩和することもできます。
AWS WAFは、SQLインジェクションやXSSといったレイヤー7攻撃に対する保護を提供します。加えて、レートベースルールを使ってDDoS攻撃を緩和することもできます。
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-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秒であるため、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.
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まとめ
CloudFrontディストリビューションを、上限100リクエストのWAFレートベースルールの背後に配置してデプロイしたところ、閾値を超えたトラフィックが403レスポンスでブロックされることがわかりました。このルールをテストする際に最も混乱しやすいのが、30秒の評価ウィンドウです。制限を大きく超えるバーストトラフィックでも、最初の30秒ほどは通過してしまうことがあり、これは一見するとルールが機能していないように見えますが、実際には単に独自のスケジュールで評価されているだけです。この組み込みの遅延と、レート制限における10,000IPという上限が、冒頭の注意書きでこれをDDoS防止ではなく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にデプロイする
Lambda Web Adapterを使うと、FastAPIで書いたAPIバックエンドをコンテナのまま単一の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インスタンスを起動・停止します。
