ALBへのAWS WAF適用 ── レートベースルールで大量リクエストを止める

目次

概要

多数のIPアドレスから読み取りリクエストが大量に届き、バックエンドのアプリケーションサーバーがスレッドを使い切って応答しなくなる。DDoSと呼ぶほど大規模でなくても、スクレイピングや壊れたクライアントのリトライで簡単に起きる状況です。

このとき、アプリケーション側でスレッド数を増やす、インスタンスをスケールアウトする、といった対処は根本解決になりません。過剰なリクエストがアプリケーションに届く前に落とすのが正しい層での対処です。

Application Load Balancer(ALB)にはAWS WAFを直接関連付けることができ、レートベースルールを使うと「一定時間内に同じ送信元から来たリクエスト数」で自動的にブロックできます。送信元IPが多数に分散していても、集約キーを変えることで対応できます。

この記事では、ALBの前段にWAFのWeb ACLを置き、レートベースルールで過剰なリクエストを遮断するまでを構築して確認します。

ALBの前段にWAFのWeb ACLを配置し、レートベースルールが過剰なリクエストを遮断する構成図
ALBの前段にWAFのWeb ACLを配置し、レートベースルールが過剰なリクエストを遮断する構成図
クラウドおさる

過剰なリクエストは、アプリケーションに届く前に落とすのが正しい層での対処でござる。この記事では、ALB に WAF の Web ACL を関連付け、レートベースルールで 403 が返り始めるところまで、弊猿と一緒に確かめるでござるな。

この記事のメリット

  • AWS WAFを関連付けられるリソースと、その中でALBを選ぶ理由を説明できるようになる
  • レートベースルールの評価ウィンドウ・集約キー・制限値の意味を正確に理解できる
  • Web ACLのルール優先順位とデフォルトアクションの関係を把握できる
  • ブロックされたリクエストをサンプルリクエストで確認し、どのルールで落ちたかを追えるようになる
  • 新しいWAFコンソールの「保護パック」の選び方と、有効にするルールによる月額の違いを画面で判断できるようになる
  • SCS試験で「大量リクエストへの最もシンプルな対策」を問う設問に正確に答えられるようになる

執筆者とキャラクター紹介

執筆者:土肥(とひ)

株式会社ジェニュインの代表であり元エンジニア。これまでオンプレミスと AWS 環境のインフラ業務を担当。AWS 認定資格の学習で得た知識を、ハンズオンとともに解説するのが得意。直近では新人の教育も行っており、これから技術を学ぶ方が納得できる解説を心がけています。基礎編・Cloud Practitioner の記事では、解説役としても登場します。

土肥

クラウドおさる

クラウドおさる

はじめましてでござる。弊猿はクラウドおさる。IT インフラが異常に発達した猿山から、雲に乗って地上の AWS を学びに降りてきたのでござる。

クラウドおさる

基礎編や Cloud Practitioner の記事では、とひさんに素朴な疑問をぶつける役でござるな。Security - Specialty などの記事では、要所でワンポイントや注意点をひとこと添えるでござる。

クラウドおさる

猿山にもデータセンターや監視当番があって、地上で起きることはだいたい猿山にも同じ仕組みがあるのでござる。例え話がつい猿山に寄るのは、弊猿の癖でござる。

技術解説

WAFはどこに置けるか

AWS WAFのWeb ACLは、次のリソースに関連付けられます。

関連付け先スコープ用途
Application Load BalancerリージョンALB配下のアプリケーション全般
Amazon CloudFront ディストリビューショングローバル(CloudFront)エッジで落としたい場合
Amazon API Gateway REST APIリージョンAPI単位の保護
AWS AppSync GraphQL APIリージョンGraphQL APIの保護
Amazon Cognito ユーザープール / App Runner / Verified Accessリージョン各サービスの保護

Network Load Balancer(NLB)には関連付けられません。NLBはL4のロードバランサーで、HTTPリクエストの中身を見ないためです。設問で「NLBにWAFを付ける」という選択肢が出たら誤りです。

すでにALBがある構成なら、ALBにWeb ACLを関連付けるのが最短で、アプリケーションの変更も要りません。CloudFrontを挟めばエッジで落とせますが、そのためだけにCloudFrontを導入するのは「最もシンプル」からは外れます。

クラウドおさる

WAF を関連付けられるのは ALB や CloudFront、API Gateway などで、L4 の NLB には付けられぬのでござる。「NLB に WAF」という組み合わせは取り違えやすいので気をつけるでござるぞ。

レートベースルールの仕組み

レートベースルールは、指定した評価ウィンドウの中で、集約キーごとにリクエスト数を数え、制限値を超えたらルールのアクション(通常はBlock)を適用します。

設定選べる値補足
レート制限最小 10評価ウィンドウ内のリクエスト数
評価ウィンドウ60 / 120 / 300 / 600 秒既定は 300 秒(5分)
集約キー送信元IP / 転送されたIP(X-Forwarded-For など) / カスタムキー / すべてカウントカスタムキーではヘッダー・クッキー・クエリ・URIパス・HTTPメソッドなどを組み合わせられる

重要な性質として、AWS WAFは制限値の「近く」でレート制限を適用しますが、完全に一致することは保証しません。「ちょうど100リクエスト目からブロックされる」と考えず、しきい値付近で効き始めるものと理解します。

ブロックは、そのキーのリクエストレートが制限を下回るまで継続します。恒久的なブロックではありません。

レートベースルールの評価(評価ウィンドウ内で集約キーごとにカウントし、しきい値超過でブロックする流れ)
レートベースルールの評価(評価ウィンドウ内で集約キーごとにカウントし、しきい値超過でブロックする流れ)

集約キーの選び方

「多数のIPから来る」場合、送信元IP単位では1つあたりのレートが低くなり、ルールに引っかからないことがあります。この場合は集約キーを変えます。

状況集約キー
単一または少数のIPから大量送信元IPアドレス
CloudFrontやプロキシの背後転送されたIPアドレス(X-Forwarded-For)
特定のAPIパスだけが叩かれるカスタムキー(URIパス)+スコープダウンステートメント
ログイン試行が多いカスタムキー(HTTPメソッド + URIパス、必要ならヘッダー)

スコープダウンステートメントを併用すると、「/search へのGETリクエストだけを対象にレートを数える」といった絞り込みができます。

クラウドおさる

送信元が多数の IP に分散していると、IP 単位では 1 つあたりのレートが低くなり、ルールに引っかからないことがあるのでござる。猿山でも、猿ごとにバナナの持ち出し回数を数えていると、大勢が少しずつ持っていく手口は見逃すでござろう。そういうときは、URI パスなどのカスタムキーに数える単位を変えるのでござる。

Web ACLの評価順序

Web ACLは、ルールを優先順位の小さい順に評価し、いずれかのルールがBlockまたはAllowと判定した時点で評価を終えます。どのルールにも一致しなかったリクエストにはデフォルトアクションが適用されます。

設定意味
デフォルトアクション: Allowルールに一致しないものは通す(ブロックリスト型)
デフォルトアクション: Blockルールに一致しないものは落とす(許可リスト型)

一般的なWebサイトの保護ではデフォルトアクションを Allow にし、レートベースルールやマネージドルールで危険なものだけを落とします。

なお、いきなり Block にすると正規の利用者を巻き込む恐れがあるため、まずアクションを Count にして様子を見る運用が定石です。Countはブロックせずに一致件数だけを記録します。

フリーランス案件
クラウドおさる
クラウドキャリアフリーランス

AWS の実務経験があるなら、単価を上げにいく

AWS に特化したフリーランスエージェントです。以下は取り扱い案件の一例です。設計・SRE・セキュリティ・生成 AI の領域で、専門を掛け合わせるほど単価が上がります。

横にスクロールできます。掲載時点の情報のため、募集が終了している場合があります。条件の近い案件をご紹介しますので、お気軽にご相談ください。

実践

既存のALB構成に対してWeb ACLを作成し、レートベースルールで過剰なリクエストが遮断されることを確認します。

前提条件

  • リージョン: ap-northeast-1(東京)
  • 以下のリソースが作成済みであること
リソース種別リソース名用途
VPCwaf-lab-vpc検証用VPC(CIDR: 10.30.0.0/16)
パブリックサブネットwaf-lab-public-ap-northeast-1a / -1cALB配置用(2AZ)
セキュリティグループwaf-lab-web-sgEC2用(VPC内からのHTTPを許可)
EC2インスタンスwaf-lab-web-ap-northeast-1a / -1cHTTPを返すWebサーバー2台

[!NOTE] 前提環境のTerraform資材は assets/56_q96_alb-waf-rate-based-rule にあります。ALBとWeb ACLは時間・月額の課金対象です(Web ACLは1つあたり月額 5 USD、ルール1つにつき月額 1 USD、いずれも時間割り。これに処理したリクエスト数に応じた料金が加わります)。検証後は削除してください。

このハンズオンで作成するリソースは以下のとおりです。

リソース種別リソース名用途
セキュリティグループwaf-lab-alb-sgALB用(インターネットからのHTTPを許可)
ターゲットグループwaf-lab-tgEC2 2台を登録
Application Load Balancerwaf-lab-albWAFの関連付け先
Web ACL(保護パック)waf-lab-web-aclレートベースルールを持つWeb ACL

手順1: ALB用のセキュリティグループを作成する

AWSマネジメントコンソールにログインし、リージョンが ap-northeast-1(東京)であることを確認します。

上部の検索バーに EC2 と入力し、「EC2」を選択します。左側ナビゲーションの「ネットワーク&セキュリティ」→「セキュリティグループ」を選択し、「セキュリティグループを作成」をクリックします。

以下を設定します。

  • セキュリティグループ名: waf-lab-alb-sg
  • 説明: ALB for WAF lab
  • VPC: waf-lab-vpc
  • インバウンドルール: タイプ HTTP、ソース マイIP
ALB用セキュリティグループのインバウンドルール設定画面
ALB用セキュリティグループのインバウンドルール設定画面

「セキュリティグループを作成」をクリックします。

手順2: ターゲットグループとALBを作成する

左側ナビゲーションの「ロードバランシング」→「ターゲットグループ」を選択し、「ターゲットグループの作成」をクリックします。

  • ターゲットタイプ: インスタンス
  • ターゲットグループ名: waf-lab-tg
  • プロトコル・ポート: HTTP / 80
  • VPC: waf-lab-vpc

「次へ」をクリックし、waf-lab-web-ap-northeast-1a と -1c の2台を選択して「保留中として以下を含める」をクリックし、「ターゲットグループの作成」で作成します。

ターゲットグループにEC2 2台を登録した画面
ターゲットグループにEC2 2台を登録した画面

左側ナビゲーションの「ロードバランサー」を選択し、「ロードバランサーの作成」をクリックします。ロードバランサータイプを比較する画面が表示されるので、「Application Load Balancer」の「作成」をクリックします。

以下を設定します。

  • ロードバランサー名: waf-lab-alb
  • スキーム: インターネット向け
  • VPC: waf-lab-vpc
  • マッピング: ap-northeast-1a と ap-northeast-1c のパブリックサブネットを選択
  • セキュリティグループ: waf-lab-alb-sg(デフォルトのSGは外す)
  • リスナー: HTTP:80 → 転送先 waf-lab-tg
ALB作成画面のネットワークマッピングとセキュリティグループ設定
ALB作成画面のネットワークマッピングとセキュリティグループ設定

「ロードバランサーの作成」をクリックし、状態が「アクティブ」になるまで待ちます。

DNS名をブラウザで開き、Webサーバーの応答が返ることを確認します。

ALBのDNS名にアクセスして応答が返っている状態
ALBのDNS名にアクセスして応答が返っている状態

手順3: Web ACL(保護パック)を作成してレートベースルールを追加する

[!NOTE] AWS WAFのコンソールは刷新され、Web ACLは「保護パック (ウェブ ACL)」という名前で、保護したいリソースを起点に作成する流れになりました。名前と画面構成が変わっただけで、作られるものは従来どおりのWeb ACLです。API・CLI(wafv2)の呼び出し方も変わりません。画面上部の案内から「以前のコンソールに切り替えてください」を選ぶと、従来の画面も使えます。

上部の検索バーに WAF と入力し、「WAF & Shield」を選択します。

「リソースと保護パック (ウェブ ACL)」の画面が開きます。「リージョンのスコープ」が CloudFront (グローバル) とリージョンレベル になっていることを確認し、「保護パック (ウェブ ACL) を作成」をクリックします。

アプリについて教えてください のセクションで、以下を選択します。ここで選んだ内容は、次のステップで推奨されるルールの内容に反映されます。

  • アプリカテゴリ: コンテンツおよび公開システム
  • アプリケーションフォーカス: ウェブ

保護するリソースを選択 のセクションで「リソースを追加」→「リージョンリソースを追加」を選びます。ダイアログに保護できるリージョンリソースの一覧が表示されるので、waf-lab-alb(Application Load Balancer)にチェックを入れて「追加」をクリックします。

初期の保護を選択 のセクションでは、ルールの組み合わせを3つから選びます。

選択肢内容
お客様のために推奨されるルール「重要」のすべて + レート制限やIPレピュテーション、Bot Controlなどを含む
重要ルールレイヤー7 DDoS対策、コアルールセット、SQLインジェクション保護などの基本セット
AWS WAF が提供するすべての保護から独自のパックを構築適用するルールを自分で選ぶ

それぞれに「1,000万リクエストあたりの推定コスト」が表示されます。マネージドルールグループを含むパックほど高くなるため、何を有効にすると課金がどう増えるかを、作る前に画面上で確認できます。

この記事ではレートベースルールだけを試すので、「AWS WAF が提供するすべての保護から独自のパックを構築」 を選択します。

名前を付けて、説明を入力 のセクションで、名前に waf-lab-web-acl を入力します。名前は後から変更できません。

保護パックの作成画面(ALBの関連付け・保護の選択・名前を設定した状態)
保護パックの作成画面(ALBの関連付け・保護の選択・名前を設定した状態)

独自のパックを選ぶと「ルールを追加」のパネルが開きます。以下の順に選択します。

  • ルールの種類: カスタムルール を選んで「次へ」
  • 作成するルール: レートベースのルール を選んで「次へ」

レートベースルールの設定画面で、以下を入力します。

  • アクション: Block
  • ルール名: rate-limit-per-ip
  • レート制限: 100
  • 評価ウィンドウ: 1 分

「ルール設定」を展開し、「リクエスト集約」が 送信元 IP アドレス になっていることを確認します。

レートベースルールの設定画面(アクション・ルール名・制限値・評価ウィンドウ・集約キーを指定した状態)
レートベースルールの設定画面(アクション・ルール名・制限値・評価ウィンドウ・集約キーを指定した状態)

「ルールを追加」をクリックします。ルールを1つ追加すると、「独自のパックを構築」の推定コストが増えることが確認できます。

画面下部の「保護パック (ウェブ ACL) を作成」をクリックします。作成が完了すると、ALBとの関連付けまで自動で行われ、「以下のリソースが関連付けられています: waf-lab-alb」というメッセージが表示されます。

一覧に戻り、waf-lab-web-acl の「ルール」列の「1 個のルール」をクリックすると、追加した rate-limit-per-ip が表示されます。

作成された保護パックとルール一覧(rate-limit-per-ip が登録されている状態)
作成された保護パックとルール一覧(rate-limit-per-ip が登録されている状態)

デフォルトアクションは新しいコンソールのウィザードには表示されませんが、既定で Allow(どのルールにも一致しないリクエストは許可)が設定されます。CLIで確認できます。

aws wafv2 get-web-acl \
    --name waf-lab-web-acl --scope REGIONAL \
    --id <Web ACL の ID> --region ap-northeast-1 \
    --query 'WebACL.{Default:DefaultAction,Rules:Rules[].{Name:Name,Action:Action,Rate:Statement.RateBasedStatement}}'
{
    "Default": { "Allow": {} },
    "Rules": [
        {
            "Name": "rate-limit-per-ip",
            "Action": { "Block": {} },
            "Rate": { "Limit": 100, "AggregateKeyType": "IP", "EvaluationWindowSec": 60 }
        }
    ]
}

手順4: 制限を超えるリクエストを送ってブロックを確認する

手元の端末から、ALBのDNS名に対して短時間に大量のリクエストを送ります。

ALB=<ALBのDNS名>
for i in $(seq 1 300); do
  curl -s -o /dev/null -w "%{http_code}\n" "http://$ALB/"
done | sort | uniq -c

1回目の実行では、すべて 200 が返ることがあります。

 300 200

これは設定が効いていないのではなく、レート制限が効き始めるまでに時間差があるためです。AWS WAFは評価ウィンドウの設定とは別のタイミングでリクエストレートを繰り返しチェックしており、しきい値を超えた瞬間にブロックが始まるわけではありません。

リクエストを送り続けると、やがてブロックが始まります。

for round in 1 2 3; do
  seq 1 200 | xargs -P 10 -I{} curl -s -o /dev/null -w "%{http_code}\n" "http://$ALB/" \
    | sort | uniq -c | tr '\n' ' '
  echo
done
 200 403
 200 403
 200 403

送信元IPあたりのレートが制限を超えた状態が続く間、そのIPからのリクエストは 403 で遮断され続けます。

[!NOTE] AWS WAFは設定した制限の近くでレート制限を適用しますが、制限との完全一致は保証しません。「ちょうど100件目から403になる」とは考えず、しきい値付近で効き始め、少し遅れて反映されるものと理解します。

クラウドおさる

1 回目はすべて 200 が返ることがあり、送り続けるとやがて 403 が混じり始めたでござるな。レートベースルールはしきい値ちょうどで効くのではなく、しきい値付近で少し遅れて効き始めるものでござる。

手順5: ブロックされたリクエストをWAF側で確認する

保護パックの一覧に戻り、waf-lab-web-acl の「サンプルリクエスト」列の「表示」をクリックします。「ダッシュボード」と「設定」の選択が表示されるので、「ダッシュボード」を選びます。

ダッシュボードの「概要」に、指定した時間範囲のリクエスト数が「合計 / 許可済み / ブロック済み」で表示されます。その下の「保護パック (ウェブ ACL) のアクティビティ」では、すべてのトラフィックが rate-limit-per-ip に入り、ブロック済みとデフォルトアクション(許可済み)に分かれていく流れが図で確認できます。

保護パックのダッシュボード(ブロックされたリクエストが記録されている状態)
保護パックのダッシュボード(ブロックされたリクエストが記録されている状態)

画面下部の「サンプルリクエスト」パネルに、直近のリクエストのサンプルが表示されます。「リクエストをフィルタ」に BLOCK と入力すると、遮断されたリクエストだけに絞り込めます。

メトリクス名の列が、許可されたリクエストでは waf-lab-web-acl(デフォルトアクション)、遮断されたリクエストでは rate-limit-per-ip(一致したルール名)になっている点に注目します。どのルールで落とされたかがここで分かります。

サンプルリクエスト(rate-limit-per-ip でブロックされたリクエストが表示されている状態)
サンプルリクエスト(rate-limit-per-ip でブロックされたリクエストが表示されている状態)

リクエストを止めてしばらく待つと、レートが制限を下回りブロックが解除されます。再度アクセスして 200 が返ることを確認します。

手順6: Countモードで影響を測る(任意)

保護パックの一覧で「ルール」列の「1 個のルール」をクリックし、「ルールを管理」のパネルから rate-limit-per-ip を開きます。

「アクション」を Count に変更し、「ルールを保存」をクリックします。

ルールのアクションをCountに変更した画面
ルールのアクションをCountに変更した画面

Countはブロックせず一致件数だけを記録します。本番環境に新しいルールを入れる前に、まずCountで「どれだけ正規のリクエストが引っかかるか」を測るのが定石です。手順3の「初期の保護を選択」で用意されているパックでも、レート制限系のルールが既定で Count になっているのは同じ考え方によるものです。

クラウドおさる

大量リクエストへの対策で、既にある ALB に Web ACL を付けてレートベースルールで落とすのが最もシンプル、と見抜けるかが問われる観点でござる。WAF を付けられないリソースや、評価ウィンドウ・集約キーの意味も、取り違えやすいところでござるな。

まとめ

論点結論
大量リクエストへの最短の対策ALBにWeb ACLを関連付け、レートベースルールで落とす
WAFを付けられないものNLB(L4のため)。ALB・CloudFront・API Gateway などが対象
レートベースルールの単位評価ウィンドウ(60/120/300/600秒、既定300秒)内の、集約キーごとのリクエスト数
制限値の下限10
効き方制限値の近くで効き始め、レートが下がると自動的に解除される
  • 送信元IPが分散している場合は、集約キーをカスタムキー(URIパスやヘッダー)に変える
  • 新しいルールはまず Count で影響を測り、問題なければ Block に切り替える
  • デフォルトアクションは、一般的なWeb公開なら Allow、許可リスト型にするなら Block
  • 検証後はWeb ACL・ALB・ターゲットグループを削除する(課金が続くため)

参照先

フリーランス案件
クラウドおさる
クラウドキャリアフリーランス

AWS の実務経験があるなら、単価を上げにいく

AWS に特化したフリーランスエージェントです。以下は取り扱い案件の一例です。設計・SRE・セキュリティ・生成 AI の領域で、専門を掛け合わせるほど単価が上がります。

横にスクロールできます。掲載時点の情報のため、募集が終了している場合があります。条件の近い案件をご紹介しますので、お気軽にご相談ください。

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

株式会社ジェニュイン(https://genuine-pt.jp)の代表取締役.

2018年〜インフラエンジニアとしてキャリアをスタートし、オンプレミスのネットワーク・サーバ環境で3年半、クラウド環境で4年半の8年間エンジニアとして従事。
2021年に佐藤氏の創業した株式会社Luxyを引き継ぎ、代表に就任。
その後アガルートグループ内の株式会社ジェニュインと合併。
合併後同社代表に就任。

目次