AWS WAFを全ルールONにして本番が落ちた話と、1年半で辿り着いたDDoS対策の現実

「とりあえず有効化」でSlackが大炎上した経験、ありませんか?マネージドルールの落とし穴からShield Advancedの費用対効果まで、1年半の本番運用で見えた現実を書きます。

WAFを「とりあえず有効化」して本番が止まった話

正直に言う。1年半前、うちのチームはAWS WAF v2のマネージドルールをほぼ全部ONにして本番デプロイした。結果、その日の夜にSlackが大騒ぎになった。

特定のAPIエンドポイントへのリクエストが軒並み403を返し始めて、最初はDDoS攻撃を受けたのかと思った。でも実態は違って、AWSManagedRulesBotControlRuleSetCategoryHttpLibraryルールが、社内で使っていたPythonのhttpxクライアントを「ボット」と判定してブロックしていたんですよね。正規の内部トラフィックが全部死んだ。

当時の対応は「COUNTモードに下げて様子見」だったけど、そもそもルールの意味を理解せずに全有効化したのが間違いだった。その失敗から1年半かけて整えた設定戦略と、2026年時点でのWAF・DDoS対策の現実を書いていく。

似たような経験をした人はAWS WAFマネージドルールを全有効化したら本番が死んだ話と、1年半で辿り着いた設定戦略も参照してほしい。より深い失敗の記録がある。


2026年のWAF脅威ランドスケープ

まず現状認識から。2026年に入って、WAFが対応しなければいけない攻撃パターンが明確に変化した。

xychart-beta
  title "WAF検知イベント種別比較(2024 vs 2026)"
  x-axis ["SQLi", "XSS", "LFI", "Bot攻撃", "AI生成攻撃", "API異常アクセス"]
  y-axis "検知数比率 (2024年=100)" 0 --> 350
  bar [100, 100, 100, 100, 0, 100]
  bar [85, 92, 78, 245, 180, 310]

従来のSQLi・XSSは微減傾向なのに対して、Bot攻撃とAPIへの異常アクセスが爆増している。特にAIを使ったクレデンシャルスタッフィングと、LLMを使って生成したSQLiペイロードの自動化が増えていて、従来のシグネチャベースのルールが追いつかないケースが出てきている。

うちのチームが2026年上半期に検知したインシデントを分類すると、こんな感じだった。

攻撃カテゴリ検知件数/月実際のブロック率誤検知率
SQLインジェクション約2,400件99.2%0.3%
XSS約1,800件98.7%0.5%
Bot(悪意あり)約45,000件87.3%3.1%
API異常アクセス約12,000件91.5%4.8%
AI生成ペイロード約3,200件72.4%1.2%
DDoS(Layer 7)約800件95.1%0.1%

Bot攻撃と誤検知の問題、これが一番しんどい。後述するけど、正規ユーザーの操作を「ボット」と判定するケースはチューニングしないと月に数千件出る。AI生成ペイロードのブロック率が72%台に留まっているのも地味に痛くて、シグネチャベースのルールだけでは限界が見えてきている。


AWS WAF v2の実践的な設定戦略

マネージドルールの選定と優先度設計

1年半運用してたどり着いた、うちの本番構成はこう。

flowchart TB
  subgraph Internet["インターネット"]
    User(["正規ユーザー"])
    Bot(["Bot / 攻撃者"])
  end

  subgraph CloudFront["CloudFront Distribution"]
    CF["CloudFront"]
  end

  subgraph WAF["AWS WAF v2 WebACL"]
    direction TB
    R1["Priority 1: IPレピュテーション (COUNT→BLOCK)"]
    R2["Priority 2: AWSManagedRulesCommonRuleSet (BLOCK)"]
    R3["Priority 3: AWSManagedRulesSQLiRuleSet (BLOCK)"]
    R4["Priority 4: BotControl (Targeted) - COUNT"]
    R5["Priority 5: カスタムルール: Rate Limiting"]
    R6["Priority 6: カスタムルール: JA3フィンガープリント"]
    R1 --> R2 --> R3 --> R4 --> R5 --> R6
  end

  subgraph ALB["Application Load Balancer"]
    LB["ALB"]
    subgraph EC2["EC2 / ECS"]
      App["アプリケーション"]
    end
  end

  User --> CF
  Bot --> CF
  CF --> WAF
  WAF --> LB
  LB --> App

重要なポイントをいくつか。

BotControlはTargetedモード一択(2026年現在)

2025年後半からTargetedモードが安定してきた。Commonモードと比べて誤検知が大幅に減って、機械学習ベースの判定精度も上がっている。ただしコストが跳ね上がるので、後述する費用の話も参照してほしい。

IPレピュテーションリストはCOUNTから始める

本番最初の2週間はCOUNTモードで観察して、自社のオフィスIPやCDN業者のIPがリストに含まれていないかを確認する。うちは最初にAkamaiのエッジIPが一部含まれていて、慌てた経験がある。

カスタムルールの実装

2026年で特に効果的だったのが、JA3フィンガープリントを使ったBot判定。AWS WAF v2はネイティブでJA3をサポートしていないので、Lambda@EdgeかCloudFront Functionsと組み合わせる。

// CloudFront Functions: JA3フィンガープリントをヘッダーに付与
function handler(event) {
  var request = event.request;
  var headers = request.headers;

  // CloudFrontはJA3ハッシュをビューワーリクエストに付与
  // cf-viewer-ja3-fingerprint ヘッダーが利用可能(2025年GA)
  var ja3 = headers['cf-viewer-ja3-fingerprint'];

  if (ja3) {
    // 既知の悪意あるJA3ハッシュリスト(定期更新)
    var blocklist = [
      'e7d705a3286e19ea42f587b344ee6865', // Mirai botnet
      '6734f37431670b3ab4292b8f60f29984', // Emotet loader
      // 2026年追加: AI生成スキャナー
      'abc123def456...',
    ];

    if (blocklist.indexOf(ja3.value) !== -1) {
      return {
        statusCode: 403,
        statusDescription: 'Forbidden',
        body: JSON.stringify({ error: 'Access denied' })
      };
    }
  }

  return request;
}

これ単体では限界があるけど、WAFのRate Limitingと組み合わせると効果が高い。

Rate Limitingのカスタムルール(実際に使っているもの)

# WAFルール定義(Python CDKで書いている)
from aws_cdk import aws_wafv2 as wafv2

# APIエンドポイント別にRate Limitを設定
api_rate_limit_rule = wafv2.CfnWebACL.RuleProperty(
    name="ApiRateLimit",
    priority=5,
    action=wafv2.CfnWebACL.RuleActionProperty(
        block=wafv2.CfnWebACL.BlockActionProperty(
            custom_response=wafv2.CfnWebACL.CustomResponseProperty(
                response_code=429,
                response_headers=[
                    wafv2.CfnWebACL.CustomHTTPHeaderProperty(
                        name="Retry-After",
                        value="60"
                    )
                ]
            )
        )
    ),
    statement=wafv2.CfnWebACL.StatementProperty(
        rate_based_statement=wafv2.CfnWebACL.RateBasedStatementProperty(
            limit=1000,  # 5分間に1000リクエスト
            aggregate_key_type="FORWARDED_IP",
            forwarded_ip_config=wafv2.CfnWebACL.ForwardedIPConfigProperty(
                header_name="X-Forwarded-For",
                fallback_behavior="MATCH"
            ),
            scope_down_statement=wafv2.CfnWebACL.StatementProperty(
                byte_match_statement=wafv2.CfnWebACL.ByteMatchStatementProperty(
                    search_string="/api/",
                    field_to_match=wafv2.CfnWebACL.FieldToMatchProperty(
                        uri_path={}
                    ),
                    text_transformations=[
                        wafv2.CfnWebACL.TextTransformationProperty(
                            priority=0,
                            type="LOWERCASE"
                        )
                    ],
                    positional_constraint="STARTS_WITH"
                )
            )
        )
    ),
    visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty(
        cloud_watch_metrics_enabled=True,
        metric_name="ApiRateLimit",
        sampled_requests_enabled=True
    )
)

FORWARDED_IP を使っているのはCloudFront経由でALBに来るから、実際のクライアントIPを取得するため。これを忘れるとCloudFrontのエッジIPに対してRate Limitがかかって全ユーザーがブロックされるという惨事になる。これも1回やった。


Shield Advancedの現実的な費用対効果

正直なことを言うと、Shield Advancedは月額3,000USDの固定費がかかる。これを正当化できるかどうかがずっと悩みどころだった。

pie title Shield Advanced費用内訳(月次)
  "固定サブスクリプション" : 3000
  "データ転送料(DDoS軽減分)" : 450
  "Advanced Shield Events対応" : 0

うちのチームが採用した判断基準はこれ。

評価項目Shield StandardShield Advancedうちの判断
Layer 3/4 DDoS軽減◎(自動緩和強化)Advancedが必要
Layer 7 DDoS(HTTP Flood)△(WAFと手動対応)○(WAF自動対応)決め手
DRT(DDoS Response Team)サポート深夜対応考慮
コスト保護(DDoS起因の費用補填)重要
WAF料金含む○(一部)実質割安
月額コスト無料$3,000〜ハードル高い

結論として、月間トラフィックが1億リクエスト超えていてサービス停止が1時間でも許容できないなら、Advancedは投資対効果が合うと判断した。DDoS起因の転送費用補填だけで元が取れた月もある。

ただし小規模サービスならShield Standard + WAF v2 + CloudFrontで十分なケースも多い。Shield AdvancedはSLAが厳しいサービスかどうかで判断すべきで、「なんとなく不安だから」という理由で入れると月3,000ドルがじわじわ効いてくる。

Shield AdvancedとWAFの連携設定

2026年現在、Shield AdvancedのATP(Advanced Detection)とWAF v2のBotControlを組み合わせる構成が使いやすくなった。

sequenceDiagram
  autonumber
  participant Attacker as 攻撃者
  participant Shield as Shield Advanced
  participant WAF as WAF v2
  participant App as アプリ
  participant DRT as DRT(AWS)

  Attacker->>Shield: L3/L4 DDoS開始
  Shield->>Shield: 自動軽減(BGPアドバタイズ変更)
  Note over Shield: 数分以内に自動対応

  Attacker->>WAF: L7 HTTP Flood開始
  WAF->>WAF: Rate Limitingで検知
  WAF->>Shield: アラート送信
  Shield->>DRT: エスカレーション(Proactive Engagementが有効な場合)
  DRT->>WAF: カスタムルール追加
  WAF->>Attacker: ブロック
  WAF->>App: 正規リクエストは通過

Proactive Engagement(積極的な関与)機能を有効にしておくと、DRTが自動でWAFルールを追加してくれる。深夜に大規模DDoSが来たとき、これに助けられた。セットアップ方法はシンプルで、Route 53 Health Checkを設定してShield AdvancedのProactive Engagementと紐付けるだけ。


実際に痛い目を見た設定ミスTOP3

「知ってれば防げた」というやつを正直に書いておく。

1. WCU(Web ACL Capacity Unit)の上限に引っかかる

WAF v2にはWCUという容量単位があって、デフォルトが1,500WCU。マネージドルールを複数追加すると簡単に超える。

# WCU消費を確認するAWS CLI
aws wafv2 check-capacity \
  --scope CLOUDFRONT \
  --rules file://rules.json \
  --region us-east-1

# 出力例
{
  "Capacity": 1847  # ← 1500超えていてデプロイ失敗
}

BotControlのTargetedモードは500WCU消費する。これを知らずに入れると他のルールが追加できなくなる。解決策はWCU上限を引き上げる(Service Quotasから申請可)か、不要なルールグループを見直すか。個人的にはまず不要ルールの棚卸しをおすすめする。申請して上限を増やしても、管理が複雑になるだけだった。

2. CloudFrontのGeography制限とWAFの評価順序

CloudFrontにはGeo Restriction機能があって、WAF v2にも同様のルールが作れる。両方設定するとCloudFrontのGeo Restrictionが先に評価されるので、WAFのGeo制限ルールは実際には動かない。これを知らずに「WAFでブロックしてるはず」と思い込んで、ログを見て混乱した。地味にハマりやすいので注意してほしい。

3. サンプリングログの落とし穴

WAFのサンプリングログは全リクエストの一部しか記録しない。大量攻撃時に「ブロックされた証拠が少ない」という状態になって、運用判断を誤りやすい。

Kinesis Data Firehoseを使ったフルログ記録は必須。ただしコストがかかるので、攻撃パターンが安定したらフィルタリングルールを追加して費用を抑えている。

// WAFログフィルター設定(Action=BLOCKのみ記録)
{
  "LoggingConfiguration": {
    "ResourceArn": "arn:aws:wafv2:...",
    "LogDestinationConfigs": [
      "arn:aws:firehose:..."
    ],
    "LoggingFilter": {
      "DefaultBehavior": "DROP",
      "Filters": [
        {
          "Behavior": "KEEP",
          "Conditions": [
            {
              "ActionCondition": {
                "Action": "BLOCK"
              }
            }
          ],
          "Requirement": "MEETS_ANY"
        }
      ]
    }
  }
}

これでログ量を70%削減できた。COUNTイベントは定期的にサンプルで確認するだけで十分だった。

インシデント対応の基本はインシデント対応の最新ベストプラクティス2026にまとまっているので、WAFアラート対応のフローと合わせて読んでみてほしい。


運用コスト最適化

1年半で試行錯誤した結果のコスト感覚を共有する。

xychart-beta
  title "WAF運用コスト推移(月次・万円)"
  x-axis ["1ヶ月目", "3ヶ月目", "6ヶ月目", "9ヶ月目", "12ヶ月目", "18ヶ月目"]
  y-axis "コスト(万円)" 0 --> 60
  line [52, 48, 35, 28, 24, 21]

最初の3ヶ月は設定が甘くて無駄なルールやログが多かった。6ヶ月目以降は最適化が進んで安定してきた感じ。最終的に初月比で約60%削減できたのは、地味にでかい成果だったと思っている。

具体的に効いたコスト削減施策を3つ挙げる。

BotControlはCOUNTモードで監視専用にする期間を設ける

全ルールBLOCKにする前に1ヶ月COUNTで動かして、誤検知パターンを把握する。これで後から対応する修正コストが大幅に減った。焦ってBLOCKに切り替えると、誤検知対応で余計な工数が飛んでいく。

WebACLを環境別に分けない(Staging共有)

WebACLは1つ作るだけで月5USDだが、複数作るとルール管理が複雑になる。StagingとProductionで別にするより、環境別のRate Limit値をルールラベルで管理する方が圧倒的に楽だった。

CloudFrontのキャッシュヒット率を上げてWAF評価回数を減らす

WAFはリクエスト数課金なので、CloudFrontでキャッシュできるレスポンスを増やすのが実は一番コスパが良い。静的コンテンツのキャッシュ率を65%から88%に上げたら、WAFのリクエスト評価数が月3,200万回→1,700万回に減った。WAFの設定を頑張る前にキャッシュ戦略を見直す、というのが正直おすすめの順番。

セキュリティ全般の実装についてはOWASP Top 10 2024対策|脆弱性10項目の実装方法と企業の守り方と合わせて設計すると漏れが減る。WAFだけではOWASP Top 10の全項目はカバーできないので注意してほしい。


まとめ

1年半の本番運用から、特に伝えたいことを整理する。

#要点補足
1マネージドルール全有効化は絶対やらない最初はCOUNTで2〜4週間観察してから段階移行
2BotControlはTargeted + JA3の組み合わせCommonモードは誤検知が多すぎる
3Shield Advancedの採用基準を明確に月1億リクエスト超・SLA厳格・深夜対応コスト高ならOK
4Rate LimitingはForwarded IP必須CloudFront経由ではX-Forwarded-Forを必ず指定
5WAFログはBLOCKのみフィルタリング全量記録は大規模攻撃時にコストが予測不能になる

今すぐできる確認事項

  • aws wafv2 check-capacity でWCU使用量を確認する
  • CloudWatchのWAFメトリクスダッシュボードを作って誤検知率を可視化する
  • Rate Limitingルールに FORWARDED_IP が正しく設定されているか確認する

皆さんのチームはWAFのチューニング、どれくらい丁寧にやっていますか?「最初に全部有効化して放置」という構成のまま運用しているケースを結構見かけるんですよね。正直まだ完璧ではないし、AI生成ペイロードへの対応は今も検証中だけど、少なくとも「ルールを入れたら終わり」という考えは2026年では通用しない。運用し続けることがWAFの本質だと、痛い目を見て初めてわかった。

U

Untanbaby

ソフトウェアエンジニア|AWS / クラウドアーキテクチャ / DevOps

10年以上のIT実務経験をもとに、現場で使える技術情報を発信しています。 記事の誤りや改善点があればお問い合わせからお気軽にご連絡ください。

関連記事