一覧に戻る
Security & CDN

WAF & Shield によるセキュリティ強化構成

AWS WAF v2 のマネージドルール(共通ルールセット・SQLi・IP評判リスト)とレートベース制限を CloudFront および ALB に適用し、DDoS・OWASP Top 10 攻撃からアプリケーションを多層防御します。

構成要素 (AWS Services):

WAFShieldCloudFrontALBCloudWatch

構築される主要リソース (6種):

WAFv2 IPSet2
WAFv2 WebACL2
CloudWatch Alarm2
WAFv2 WebACLAssociation1
Logs LogGroup1
WAFv2 LoggingConfiguration1

アーキテクチャ図 (Architecture Diagram)

クリックで拡大表示
WAF & Shield によるセキュリティ強化構成 アーキテクチャ図

AWS CLI でのデプロイ例

AWS CLIを使用してCloudFormationスタックをデプロイする場合は、以下のコマンドを実行します。

aws cloudformation deploy \
  --template-file waf-shield-security.yaml \
  --stack-name waf-shield-security-stack \
  --capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM
waf-shield-security.yaml
DL
AWSTemplateFormatVersion: '2010-09-09'
Description: 'WAF v2 & Shield Advanced security hardening with CloudFront and ALB - Best Practices'

Parameters:
  Environment:
    Type: String
    Default: production
    AllowedValues: [production, staging, development]
  ALBArn:
    Type: String
    Description: ARN of the existing ALB to associate WAF with (leave empty to skip ALB association)
    Default: ''
  RateLimitThreshold:
    Type: Number
    Default: 2000
    Description: Max requests per 5 minutes per IP

Conditions:
  AssociateWithALB: !Not [!Equals [!Ref ALBArn, '']]

Resources:
  # IP Set for allowlist (optional)
  AllowedIPSet:
    Type: AWS::WAFv2::IPSet
    Properties:
      Scope: CLOUDFRONT
      IPAddressVersion: IPV4
      Addresses: []

  # IP Set for blocklist
  BlockedIPSet:
    Type: AWS::WAFv2::IPSet
    Properties:
      Scope: CLOUDFRONT
      IPAddressVersion: IPV4
      Addresses: []

  # WAF Web ACL (CloudFront scope - must be us-east-1)
  WebACL:
    Type: AWS::WAFv2::WebACL
    Properties:
      Scope: CLOUDFRONT
      DefaultAction:
        Allow: {}
      VisibilityConfig:
        SampledRequestsEnabled: true
        CloudWatchMetricsEnabled: true
        MetricName: !Sub ${AWS::StackName}-WebACL
      Rules:
        # AWS Managed Rules - Common Rule Set
        - Name: AWSManagedRulesCommonRuleSet
          Priority: 10
          OverrideAction:
            None: {}
          Statement:
            ManagedRuleGroupStatement:
              VendorName: AWS
              Name: AWSManagedRulesCommonRuleSet
          VisibilityConfig:
            SampledRequestsEnabled: true
            CloudWatchMetricsEnabled: true
            MetricName: AWSManagedRulesCommonRuleSet

        # AWS Managed Rules - Known Bad Inputs
        - Name: AWSManagedRulesKnownBadInputsRuleSet
          Priority: 20
          OverrideAction:
            None: {}
          Statement:
            ManagedRuleGroupStatement:
              VendorName: AWS
              Name: AWSManagedRulesKnownBadInputsRuleSet
          VisibilityConfig:
            SampledRequestsEnabled: true
            CloudWatchMetricsEnabled: true
            MetricName: AWSManagedRulesKnownBadInputsRuleSet

        # AWS Managed Rules - SQL Injection
        - Name: AWSManagedRulesSQLiRuleSet
          Priority: 30
          OverrideAction:
            None: {}
          Statement:
            ManagedRuleGroupStatement:
              VendorName: AWS
              Name: AWSManagedRulesSQLiRuleSet
          VisibilityConfig:
            SampledRequestsEnabled: true
            CloudWatchMetricsEnabled: true
            MetricName: AWSManagedRulesSQLiRuleSet

        # AWS Managed Rules - Amazon IP Reputation List
        - Name: AWSManagedRulesAmazonIpReputationList
          Priority: 40
          OverrideAction:
            None: {}
          Statement:
            ManagedRuleGroupStatement:
              VendorName: AWS
              Name: AWSManagedRulesAmazonIpReputationList
          VisibilityConfig:
            SampledRequestsEnabled: true
            CloudWatchMetricsEnabled: true
            MetricName: AWSManagedRulesAmazonIpReputationList

        # Block listed IPs
        - Name: BlockListedIPs
          Priority: 50
          Action:
            Block: {}
          Statement:
            IPSetReferenceStatement:
              Arn: !GetAtt BlockedIPSet.Arn
          VisibilityConfig:
            SampledRequestsEnabled: true
            CloudWatchMetricsEnabled: true
            MetricName: BlockListedIPs

        # Rate limiting per IP
        - Name: RateLimitPerIP
          Priority: 60
          Action:
            Block: {}
          Statement:
            RateBasedStatement:
              Limit: !Ref RateLimitThreshold
              AggregateKeyType: IP
          VisibilityConfig:
            SampledRequestsEnabled: true
            CloudWatchMetricsEnabled: true
            MetricName: RateLimitPerIP

  # WAF Web ACL for ALB (Regional scope)
  RegionalWebACL:
    Type: AWS::WAFv2::WebACL
    Properties:
      Scope: REGIONAL
      DefaultAction:
        Allow: {}
      VisibilityConfig:
        SampledRequestsEnabled: true
        CloudWatchMetricsEnabled: true
        MetricName: !Sub ${AWS::StackName}-RegionalWebACL
      Rules:
        - Name: AWSManagedRulesCommonRuleSet
          Priority: 10
          OverrideAction:
            None: {}
          Statement:
            ManagedRuleGroupStatement:
              VendorName: AWS
              Name: AWSManagedRulesCommonRuleSet
          VisibilityConfig:
            SampledRequestsEnabled: true
            CloudWatchMetricsEnabled: true
            MetricName: RegionalAWSManagedRulesCommonRuleSet

        - Name: AWSManagedRulesAmazonIpReputationList
          Priority: 20
          OverrideAction:
            None: {}
          Statement:
            ManagedRuleGroupStatement:
              VendorName: AWS
              Name: AWSManagedRulesAmazonIpReputationList
          VisibilityConfig:
            SampledRequestsEnabled: true
            CloudWatchMetricsEnabled: true
            MetricName: RegionalAWSManagedRulesAmazonIpReputationList

        - Name: RegionalRateLimitPerIP
          Priority: 30
          Action:
            Block: {}
          Statement:
            RateBasedStatement:
              Limit: !Ref RateLimitThreshold
              AggregateKeyType: IP
          VisibilityConfig:
            SampledRequestsEnabled: true
            CloudWatchMetricsEnabled: true
            MetricName: RegionalRateLimitPerIP

  # Associate Regional WAF with ALB (conditional)
  ALBWebACLAssociation:
    Type: AWS::WAFv2::WebACLAssociation
    Condition: AssociateWithALB
    Properties:
      ResourceArn: !Ref ALBArn
      WebACLArn: !GetAtt RegionalWebACL.Arn

  # WAF Logging Configuration
  WAFLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub aws-waf-logs-${AWS::StackName}
      RetentionInDays: 90

  WAFLoggingConfiguration:
    Type: AWS::WAFv2::LoggingConfiguration
    Properties:
      ResourceArn: !GetAtt RegionalWebACL.Arn
      LogDestinationConfigs:
        - !GetAtt WAFLogGroup.Arn

  # CloudWatch Alarms for WAF
  WAFBlockedRequestsAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmDescription: Alert when WAF blocks more than 100 requests in 5 minutes
      Namespace: AWS/WAFV2
      MetricName: BlockedRequests
      Dimensions:
        - Name: WebACL
          Value: !Ref RegionalWebACL
        - Name: Region
          Value: !Ref AWS::Region
        - Name: Rule
          Value: ALL
      Statistic: Sum
      Period: 300
      EvaluationPeriods: 1
      Threshold: 100
      ComparisonOperator: GreaterThanThreshold
      TreatMissingData: notBreaching

  WAFRateLimitAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmDescription: Alert when rate limit rule triggers frequently
      Namespace: AWS/WAFV2
      MetricName: BlockedRequests
      Dimensions:
        - Name: WebACL
          Value: !Ref RegionalWebACL
        - Name: Region
          Value: !Ref AWS::Region
        - Name: Rule
          Value: RegionalRateLimitPerIP
      Statistic: Sum
      Period: 300
      EvaluationPeriods: 1
      Threshold: 50
      ComparisonOperator: GreaterThanThreshold
      TreatMissingData: notBreaching

Outputs:
  CloudFrontWebACLArn:
    Description: WAF Web ACL ARN for CloudFront (us-east-1 only)
    Value: !GetAtt WebACL.Arn
  RegionalWebACLArn:
    Description: WAF Web ACL ARN for ALB/API Gateway (regional)
    Value: !GetAtt RegionalWebACL.Arn
  WAFLogGroupName:
    Description: CloudWatch Log Group for WAF logs
    Value: !Ref WAFLogGroup