AWS WAFのレートベースルールとは、一定時間内に同じ条件へ該当するリクエストが多すぎる場合に、その後のリクエストへ制御をかけるルールです。
たとえば、同じIPアドレスから短時間に大量のアクセスがあった場合や、ログインフォームに対して連続してPOSTリクエストが送られている場合に、AWS WAFがそのアクセスを検知し、Block、Count、CAPTCHA、Challengeなどのアクションを適用できます。
主な用途は、以下のような高頻度アクセスへの対策です。
・短時間の大量アクセス対策
・ログインブルートフォース対策
・スクレイピング対策
・問い合わせフォームのスパム対策
・APIへの過剰アクセス対策
・アプリケーションレイヤーの簡易的なDDoS緩和
ただし、AWS WAFのレートベースルールは、厳密なAPIレートリミッターではありません。
「1分間に60回まで」「契約プランごとに月間10万リクエストまで」のような正確な利用量制御には向いていません。
あくまで、Webアプリケーションを高頻度アクセスやbot的な挙動から守るための防御レイヤーとして使うのが適切です。
AWS WAFのレートベースルールでは、リクエストを特定の単位でグループ化し、そのグループごとに一定時間内のリクエスト数をカウントします。
そして、設定した上限を超えた場合に、対象リクエストへ指定したアクションを適用します。
レートベースルールは、主に以下の要素で構成されます。
| 項目 | 内容 |
|---|---|
| Evaluation window | どの期間のリクエストを集計するか |
| Rate limit | その期間内に許容するリクエスト数 |
| Aggregation key | 何を単位にリクエストを数えるか |
| Scope-down statement | どのリクエストだけを対象にするか |
| Action | 閾値を超えたリクエストに何をするか |
たとえば、以下のような設定ができます。
対象: /login へのPOSTリクエスト
集約単位: IPアドレス
評価期間: 5分
上限: 100リクエスト
アクション: Block
この場合、同じIPアドレスから /login に対して5分間で100回を超えるPOSTリクエストが送信されると、その後の該当リクエストにBlockが適用されます。
Evaluation windowは、AWS WAFがリクエスト数を集計するために、どれくらい過去までさかのぼるかを指定する設定です。
現在、指定できる値は以下の4つです。
| 秒数 | 意味 |
|---|---|
| 60秒 | 1分 |
| 120秒 | 2分 |
| 300秒 | 5分 |
| 600秒 | 10分 |
デフォルトは300秒、つまり5分です。
1分のEvaluation windowは、短時間で急増するアクセスを早く検知したい場合に向いています。
たとえば、APIに対して瞬間的に大量リクエストが来るケースや、ログインフォームに対して短時間で大量試行されるケースでは、短い評価期間が有効です。
ただし、評価期間が短いほど、一時的な通常アクセスも検知されやすくなります。
通常ユーザーの連続操作や、ページ読み込み時の複数リクエストが多いサイトでは、誤検知に注意が必要です。
5分はAWS WAFのデフォルト設定であり、もっとも汎用的に使いやすい評価期間です。
ログイン試行、フォーム送信、検索ページ、サイト全体の高頻度アクセス対策など、幅広い用途で使えます。
初めてレートベースルールを導入する場合は、まず5分を基準に考えるとよいでしょう。
10分のEvaluation windowは、ゆっくり継続するスクレイピングや、短時間では目立ちにくい継続的な高頻度アクセスを検知したい場合に向いています。
たとえば、商品検索ページや記事一覧ページを長時間かけて巡回するbotへの対策では、10分の評価期間が有効な場合があります。
一方で、制限が解除されるまでの時間も長く感じられる可能性があるため、正常ユーザーを巻き込まないように慎重な設定が必要です。
Rate limitは、Evaluation window内で許容するリクエスト数です。
たとえば、以下のように設定したとします。
Evaluation window: 300秒
Rate limit: 1,000
Aggregation key: Source IP
Action: Block
この場合、同一IPアドレスから5分間で約1,000件を超えるリクエストが送信されると、そのIPアドレスからの追加リクエストが制限対象になります。
AWS WAFのレートベースルールでは、Rate limitの最小値は10です。
つまり、以下のような極端に小さい値は設定できません。
1分間に1リクエストまで
5分間に3リクエストまで
最低でも10リクエスト以上を基準に設定します。
AWS WAFのレートベースルールは、設定値付近でレート制限を適用しますが、厳密に「上限を1件でも超えた瞬間に必ず遮断する」仕組みではありません。
そのため、以下のような用途には向いていません。
・契約プランごとのAPI利用量を正確に制御したい
・課金に関わるリクエスト数を厳密に管理したい
・1ユーザーあたり毎分60リクエストまでを正確に保証したい
このような要件では、AWS WAFではなく、API Gatewayの使用量プラン、アプリケーション側のレートリミッター、Redisなどを使ったトークンバケット方式などを検討する必要があります。
Aggregation keyは、リクエストを何単位でグループ化して数えるかを決める設定です。
レートベースルールの設計では、このAggregation keyが非常に重要です。
たとえば、IPアドレス単位で集計するのか、APIキー単位で集計するのか、URIパスごとに集計するのかによって、制限のかかり方が大きく変わります。
もっとも基本的な集約キーが、Source IP addressです。
これは、AWS WAFが送信元として認識したIPアドレスごとにリクエスト数をカウントする方法です。
同じIPアドレスから5分間に1,000リクエストを超えたら制限する
というような設定ができます。
通常のWebサイトで、まず最初に検討されることが多い集約方法です。
ただし、CloudFront、ALB、リバースプロキシなどを経由している場合、AWS WAFが認識するSource IPが、必ずしも実際のクライアントIPとは限りません。
構成によっては、直前のプロキシやロードバランサーのIPが見える場合があります。
そのため、実クライアントIPをもとに制御したい場合は、Forwarded IPの利用を検討する必要があります。
Forwarded IPは、X-Forwarded-For などのHTTPヘッダーに含まれるIPアドレスをもとに集約する方法です。
CloudFrontやロードバランサー、プロキシを経由している構成で、実際のクライアントIPに近い情報を使って制限したい場合に利用します。
ただし、Forwarded IPを使う場合は、ヘッダーの信頼性に注意が必要です。
X-Forwarded-For は、構成によってはクライアント側で任意に付与できる可能性があります。
信頼できるプロキシやCDNでヘッダーが正しく付与・上書きされていることを確認したうえで利用するべきです。
また、Forwarded IPでは、指定したヘッダー内の最初のIPアドレスが集約キーとして扱われます。
そのため、どのプロキシがどの順番でIPを追加するのかを理解しておく必要があります。
Count allは、個別のIPアドレスやヘッダー値ごとに分けず、条件に一致するすべてのリクエストを1つのグループとしてカウントする方法です。
たとえば、以下のような制御ができます。
/login へのPOSTリクエスト全体が5分間で10,000件を超えたら制限する
この場合、IPアドレス単位ではなく、/login へのPOSTリクエスト全体の量を見ます。
ただし、Count allを使う場合は、Scope-down statementが必須です。
対象を絞らずに全リクエストをまとめてカウントすると、通常アクセスも含めて広範囲に影響する可能性があるためです。
Custom keysを使うと、より細かい条件でリクエストを集約できます。
たとえば、以下のような集約が可能です。
・IPアドレス + URIパス
・IPアドレス + HTTPメソッド
・Headerの値
・Cookieの値
・Query argument
・Label namespace
・APIキー
たとえば、APIキーをHTTPヘッダーで受け取っている場合、以下のような制限を設計できます。
x-api-key ごとに5分間で1,000リクエストまで
ただし、AWS WAFは厳密なレートリミッターではないため、APIキーごとの大まかな過剰アクセス抑制には使えても、契約プランごとの正確な利用量管理には向いていません。
正確なクォータ管理が必要な場合は、API Gatewayの使用量プランやアプリケーション側の制御を使うべきです。
Scope-down statementは、レート制限の対象にするリクエストを絞り込むための条件です。
AWS WAFのレートベースルールを安全に運用するうえで、Scope-down statementは非常に重要です。
サイト全体に対してレート制限をかけると、通常ユーザー、検索エンジン、広告審査bot、監視ツール、外部連携サービスなどを巻き込む可能性があります。
そこで、特定のURI、HTTPメソッド、国、ヘッダー、User-Agentなどで対象を絞り込みます。
ログインブルートフォース対策では、以下のようなScope-down statementが考えられます。
URI path = /login
AND
HTTP method = POST
この設定により、サイト全体のアクセスではなく、ログインフォームへのPOSTリクエストだけをカウントできます。
問い合わせフォームのスパム対策では、以下のような条件が考えられます。
URI path = /contact
AND
HTTP method = POST
フォーム送信は通常、短時間に何十回も行われるものではありません。
そのため、比較的低めのRate limitを設定しやすい対象です。
APIへの過剰アクセスを制限したい場合は、以下のように /api/ 配下だけを対象にできます。
URI path starts with /api/
ただし、APIはエンドポイントによって通常のリクエスト数が大きく異なる場合があります。
そのため、/api/ 全体に一律で制限をかけるよりも、URIパス、APIキー、認証情報などを組み合わせて設計したほうがよいケースもあります。
検索ページはスクレイピング対象になりやすいページです。
URI path = /search
AND
HTTP method = GET
このように検索ページだけを対象にすることで、サイト全体への影響を抑えながら、スクレイピング対策を行えます。
レートベースルールでは、閾値を超えたリクエストに対して、Allow以外のアクションを設定できます。
代表的なアクションは以下です。
| Action | 内容 |
|---|---|
| Count | ブロックせず記録だけする |
| Block | リクエストをブロックする |
| CAPTCHA | CAPTCHAを要求する |
| Challenge | ブラウザチャレンジを要求する |
Countは、リクエストをブロックせず、ルールに一致したことだけを記録するアクションです。
AWS WAFのレートベースルールを導入する際は、まずCountから始めるのがおすすめです。
いきなりBlockにすると、正常ユーザーや正規botを誤って遮断してしまう可能性があります。
Countであれば、実際のユーザー影響を出さずに、どの程度のリクエストが閾値に引っかかるかを確認できます。
初期導入時は、以下の流れが安全です。
Countで観察
↓
ログを確認
↓
閾値やScope-downを調整
↓
Challenge、CAPTCHA、Blockへ変更
Blockは、閾値を超えたリクエストを遮断するアクションです。
明らかな攻撃、悪質なスクレイピング、ログインブルートフォースなどには有効です。
ただし、Source IP単位でBlockする場合は注意が必要です。
企業ネットワーク、学校、公共Wi-Fi、モバイルキャリア回線などでは、多数のユーザーが同じIPアドレスからアクセスしているように見えることがあります。
そのため、低すぎる閾値でBlockを設定すると、正常ユーザーを巻き込む可能性があります。
CAPTCHAは、ユーザーに画像認証などの追加確認を求めるアクションです。
完全にブロックするのではなく、人間のユーザーとbotを切り分けたい場合に有効です。
問い合わせフォーム、会員登録、ログインページ、コメント投稿など、人間による操作を前提としたページでは有効な選択肢になります。
Challengeは、ブラウザに対してチャレンジを行い、正当なブラウザかどうかを確認するアクションです。
CAPTCHAよりもユーザーの操作負担が少ないケースがあり、bot対策とユーザー体験のバランスを取りたい場合に利用されます。
ただし、CAPTCHAやChallengeは、主にブラウザ向けページで使うことを前提に考えるべきです。
API、Webhook、ネイティブアプリ通信、JSONレスポンス前提のエンドポイントに対して安易に適用すると、正常なクライアントがレスポンスを処理できず、通信エラーになる可能性があります。
ここからは、実務でよく使われる設定例を紹介します。
ただし、以下の数値は公式の推奨値ではありません。あくまで初期検討用の目安です。
実際には、WAFログ、CloudFrontログ、ALBログ、アプリケーションログなどを確認しながら調整してください。
サイト全体に対して、同一IPからの過剰アクセスを抑制する設定例です。
Aggregation key: Source IP
Evaluation window: 300秒
Rate limit: 1,000〜5,000
Scope-down: なし
Action: Count → Block
この設定は、同一IPから短時間に大量アクセスが来るケースに有効です。
ただし、画像、CSS、JavaScript、API通信が多いサイトでは、通常ユーザーでも短時間に多数のリクエストが発生することがあります。
そのため、サイト全体に対して厳しいRate limitを設定する場合は、必ずCountで観察してからBlockへ移行するべきです。
ログインフォームへの連続試行を抑える設定例です。
Aggregation key: Source IP
Evaluation window: 300秒
Rate limit: 50〜200
Scope-down:
URI path = /login
HTTP method = POST
Action: Count → Challenge → Block
ログインページでは、正当なユーザーが短時間に何十回もログインを試すケースは少ないため、比較的低めの閾値を設定しやすいです。
ただし、パスワードを忘れたユーザー、社内ネットワークから複数人がアクセスするケース、SaaS型サービスのようにログイン頻度が高いケースでは、慎重な調整が必要です。
問い合わせフォームや資料請求フォームへの連続投稿を抑える設定例です。
Aggregation key: Source IP
Evaluation window: 300秒
Rate limit: 10〜50
Scope-down:
URI path = /contact
HTTP method = POST
Action: Count → CAPTCHA / Block
フォーム送信は通常ユーザーが短時間に何度も行うものではないため、比較的低いRate limitを設定できます。
ただし、フォーム送信後のリダイレクトや確認画面、バリデーションエラー時の再送信など、アプリケーションの挙動も考慮する必要があります。
検索ページや一覧ページのスクレイピングを抑える設定例です。
Aggregation key: Source IP
Evaluation window: 600秒
Rate limit: 100〜500
Scope-down:
URI path = /search
Action: Count → Challenge
検索ページは、商品情報、求人情報、記事一覧、不動産情報などを収集するbotに狙われやすいページです。
一方で、通常ユーザーも連続して検索条件を変えたり、ページネーションを操作したりすることがあります。
そのため、いきなりBlockするよりも、まずCountで確認し、その後Challengeを検討するのが安全です。
APIへの過剰アクセスを抑える設定例です。
Aggregation key: IP address + URI path
Evaluation window: 60秒または300秒
Rate limit: 実測ベースで設定
Scope-down:
URI path starts with /api/
Action: Count → Block
APIの場合、ページ表示とは異なり、1画面の表示で複数のAPIが連続して呼ばれることがあります。
そのため、Webページと同じ感覚でRate limitを低くしすぎると、正常なアプリケーション通信まで制限してしまう可能性があります。
APIでは、IPアドレスだけでなく、APIキー、認証ユーザー、URIパスなどを組み合わせて、より実態に合った集約単位を設計することが重要です。
AWS WAFのレートベースルールは便利ですが、設定を誤ると正常なユーザーや正規のシステム連携に影響を与える可能性があります。
ここでは、特に注意すべきポイントを整理します。
AWS WAFのレートベースルールは、正確な回数制御を目的とした機能ではありません。
たとえば、以下のような要件には向いていません。
・1ユーザーあたり1分60リクエストまでを厳密に守りたい
・APIキーごとに契約プラン別の上限を正確に管理したい
・課金対象のリクエスト数を厳密に制御したい
・秒単位で正確なトークンバケット制御をしたい
このような場合は、AWS WAFではなく、API Gateway、アプリケーション側の制御、Redisなどのインメモリストア、専用API管理基盤を使うほうが適しています。
レートベースルールの設定を変更すると、レート制限のカウントがリセットされる場合があります。
対象になり得る設定には、以下のようなものがあります。
・Evaluation window
・Rate limit
・Aggregation settings
・Forwarded IP configuration
・Scope-down statement
本番環境で頻繁に設定を変更すると、一時的に制限が効きにくくなる可能性があります。
そのため、変更は検証環境やCount運用で確認したうえで、慎重に反映するのが望ましいです。
Source IP単位でレート制限を行う場合、同一IPアドレスの背後に複数のユーザーがいるケースに注意が必要です。
たとえば、以下のような環境では、複数ユーザーが同じIPアドレスからアクセスしているように見える場合があります。
・企業ネットワーク
・学校や大学
・公共Wi-Fi
・モバイルキャリア回線
・NAT配下のネットワーク
この状態で閾値を低くしすぎると、1人の悪質なアクセスだけでなく、同じネットワークを利用している正常ユーザーまで制限される可能性があります。
対策としては、以下が考えられます。
・Rate limitを高めに設定する
・Scope-downで対象エンドポイントを絞る
・BlockではなくChallengeやCAPTCHAを使う
・IP以外のCustom keyを組み合わせる
・ログを見ながら除外条件を作る
Forwarded IPを使う場合は、X-Forwarded-For などのヘッダーが信頼できるかを確認する必要があります。
ヘッダーがクライアントから自由に付与できる構成になっていると、攻撃者が任意のIPアドレスを指定し、レート制限を回避する可能性があります。
そのため、Forwarded IPを使う場合は、以下を確認するべきです。
・CloudFrontやALBなど信頼できるプロキシでヘッダーを付与しているか
・クライアントが直接オリジンへアクセスできない構成になっているか
・ヘッダーの上書きルールが明確になっているか
・AWS WAFがどのIPアドレスを集約キーとして扱うか理解しているか
CAPTCHAやChallengeは、ブラウザ向けのページでは有効です。
しかし、API、Webhook、モバイルアプリのバックエンド通信、JSONレスポンス前提のエンドポイントでは注意が必要です。
これらのクライアントは、CAPTCHAやChallengeのレスポンスを適切に処理できないことがあります。
そのため、以下のように使い分けるのが安全です。
ブラウザ向けページ:
CAPTCHA / Challengeを検討しやすい
API・Webhook:
CountやBlockを中心に検討
必要に応じてアプリ側の認証・レート制限と組み合わせる
AWS WAFでは、ルールごとにWCUという処理コストの考え方があります。
レートベースルールを設計する際は、WCUとクォータも確認しておく必要があります。
AWS WAFのレートベースルールは、基本的に2 WCUです。
ただし、Custom aggregation keyを追加すると、キーごとに30 WCUが追加されます。
また、Scope-down statementを設定する場合は、その条件に必要なWCUも加算されます。
基本のレートベースルール: 2 WCU
Custom key 1つ追加: +30 WCU
Scope-down statement: 条件に応じて追加
単純なIP単位のレート制限であれば軽量ですが、複数のCustom keyや複雑なScope-downを組み合わせると、WCU消費が増える点に注意が必要です。
AWS WAFのレートベースルールには、以下のようなクォータがあります。
| 項目 | 上限 |
|---|---|
| Web ACLあたりのレートベースルール数 | 10 |
| ルールグループあたりのレートベースルール数 | 4 |
| Rate limitの最小値 | 10 |
| 単一レートベースルールで制限可能な一意IPアドレス数 | 10,000 |
これらのクォータは、複数のエンドポイントに対して細かくレート制限を設計する場合に重要です。
AWS WAFの料金は、主に以下に基づいて発生します。
・Web ACL
・Web ACL内のルール数
・処理されたリクエスト数
通常のレートベースルールは、AWS WAFの標準的な料金体系の中で考えられます。
ただし、CAPTCHA、Challenge、Bot Control、Fraud Control、Marketplace managed rule groupなどを組み合わせる場合は、追加料金が発生する可能性があります。
特にCAPTCHAやChallengeを広範囲に適用する場合は、料金影響も含めて事前に確認することが重要です。
AWS WAFのレートベースルールは、最初から完璧な閾値を設定するのではなく、ログを見ながら調整していくのが基本です。
最初に、CloudFrontログ、ALBログ、WAFログ、アプリケーションログなどを確認します。
確認すべき項目は以下です。
・IPアドレスごとの5分間リクエスト数
・/login へのPOST回数
・/contact へのPOST回数
・/api/ 配下のリクエスト数
・検索ページへの連続アクセス数
・User-Agent別のアクセス傾向
・国やASNごとのアクセス傾向
・広告botや検索エンジンbotのアクセス状況
通常時のアクセス量を把握しないまま閾値を設定すると、正常ユーザーを巻き込む可能性があります。
最初はBlockではなく、Countでルールを作成します。
Countにしておけば、実際にはブロックせず、どのリクエストがルールに一致するかを確認できます。
特に本番環境では、最初からBlockにするのではなく、Countで一定期間観察するのが安全です。
Countで記録されたリクエストを確認し、正常なアクセスが含まれていないかを見ます。
特に以下のようなアクセスが含まれている場合は注意が必要です。
・正常ユーザー
・検索エンジンbot
・広告媒体の審査bot
・社内IP
・監視ツール
・外部連携サービス
・決済サービスやWebhook
誤検知がある場合は、Rate limitを上げる、Scope-downを調整する、対象エンドポイントを分けるなどの対応を行います。
通常アクセスのピークより少し余裕を持たせてRate limitを設定します。
たとえば、通常時の最大値が「5分間で80リクエスト/IP」程度であれば、いきなり100にするのではなく、200〜300程度から始めるほうが安全です。
サイト全体に対するルールは高めに、ログインやフォーム送信など特定用途のルールは低めに設定するなど、対象ごとに分けて考えることが重要です。
Countで十分に確認したうえで、必要に応じてActionを変更します。
ブラウザ向けページであればChallengeやCAPTCHA、明らかに悪質なアクセスであればBlockを検討します。
ただし、APIやWebhookではChallengeやCAPTCHAが適さない場合があるため、エンドポイントの性質に合わせて使い分ける必要があります。
以下は、一般的なWebサイトにおける初期設定の目安です。
実際には、サイト規模、ページ構成、ユーザー行動、API利用状況、bot流入状況によって調整してください。
| 対象 | Aggregation key | Evaluation window | Rate limit | Action |
|---|---|---|---|---|
| サイト全体 | IP | 5分 | 1,000〜5,000 | Count → Block |
| ログインPOST | IP | 5分 | 50〜200 | Count → Challenge |
| 問い合わせPOST | IP | 5分 | 10〜50 | Count → CAPTCHA / Block |
| 検索ページ | IP | 10分 | 100〜500 | Count → Challenge |
| API | IP + Path / API key | 1〜5分 | 実測ベース | Count → Block |
この表はあくまで目安です。
実際にはログを確認し、正常アクセスのピークを把握したうえで設定する必要があります。
AWS WAFのレートベースルールは、短時間に大量のリクエストを送るアクセスに対して、AWS WAF側で制御をかけられる便利な機能です。
IPアドレス、Forwarded IP、Header、Cookie、Query、URIパス、APIキーなどを集約キーとして利用でき、ログイン、フォーム、検索ページ、APIなど、さまざまな用途に応用できます。
一方で、AWS WAFのレートベースルールは厳密なAPIレートリミッターではありません。
正確な利用量制御や課金に関わるクォータ管理には、API Gatewayやアプリケーション側の制御を使うべきです。
実務では、以下の考え方が重要です。
・まずCountで観察する
・サイト全体ではなく重要エンドポイントごとにScope-downする
・正常ユーザーや正規botを巻き込まないようにする
・Forwarded IPを使う場合はヘッダーの信頼性を確認する
・CAPTCHAやChallengeはAPIには慎重に使う
・推奨値をそのまま使わず、ログを見て調整する
・WebマーケティングやSEOへの影響も確認する
AWS WAFのレートベースルールは、適切に設計すれば、アプリケーションレイヤーの高頻度アクセス対策として非常に有効です。
特に、ログインフォーム、問い合わせフォーム、検索ページ、APIなど、攻撃やbotの対象になりやすい箇所に対して、Scope-down statementと組み合わせて導入することで、ユーザー体験を守りながらセキュリティを高められます。
以上、AWS WAFのレートベースルールについてでした。
最後までお読みいただき、ありがとうございました。