AWS WAF Rate-based ルールを使用して DDoS 攻撃を軽減する方法

AWS WAF Rate-based ルールを使用して DDoS 攻撃を軽減する方法

Takahiro Iwasa
(岩佐 孝浩)
Takahiro Iwasa (岩佐 孝浩)
5 min read
WAF

AWS WAF は、 SQL インジェクションや XSS などのレイヤー7攻撃に対する保護を提供します。 Rate-based ルールを使用して DDoS 攻撃を軽減することもできます。これにより、各 IP アドレスからの HTTP リクエストに対するしきい値を設定できます。この投稿では、使用方法について説明します。

概要

以下にご注意ください。

  • The minimum rate that you can set is 100. 1
  • AWS WAF checks the rate of requests every 30 seconds, and counts requests for the prior 5 minutes each time. Because of this, it’s possible for an aggregation instance to have requests coming in at too high a rate for up to 30 seconds before AWS WAF detects and rate limits the requests for the instance. 2
  • The maximum number of IP addresses that AWS WAF can rate limit using a single rate-based rule instance is 10,000. If more than 10,000 addresses exceed the rate limit, AWS WAF limits those with the highest rates. 3

AWS リソース作成

以下の内容を含む CloudFormation テンプレートを作成してください。重要なポイントは LimitAggregateKeyType (53-54行目) です。この投稿では、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

以下のコマンドを使用して CloudFormation スタックをデプロイしてください。

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

以下のコマンドを使用して、サンプルの index.html を S3 バケットにアップロードしてください。

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秒以上、毎秒リクエストを送信してください。 AWS WAF ルールによってブロックされたリクエストが 403 Forbidden のレスポンスを返すはずです。

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 1; done
Request: 1
<html><body>Hello World!</body></html>

Request: 2
<html><body>Hello World!</body></html>

Request: 3
<html><body>Hello World!</body></html>

...

Request: 126
<!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 リソースを削除してください。

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

Footnotes

  1. https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-rate-based-high-level-settings.html

  2. https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-rate-based-request-limiting.html

  3. https://docs.aws.amazon.com/waf/latest/developerguide/listing-managed-ips.html

Takahiro Iwasa
(岩佐 孝浩)

Takahiro Iwasa (岩佐 孝浩)

Software Developer at iret, Inc.
主に AWS を利用したクラウドネイティブアプリケーションの設計および開発をしています。 Japan AWS Top Engineers 2020-2023