AWS WAF カスタムルールの WCU はどのくらいなのか
はじめに
平素は大変お世話になっております。
クイックガードのパー子です。
AWS WAF を運用する際、AWSマネージドなルールを活用しつつ、カスタムルールで細部の挙動を調整することが多いかと思います。
ここで気になるのがカスタムルールの WCU (Web ACL Capacity Unit) の値です。
マネージドなルールはドキュメントに WCU値が明記されていますが、カスタムルールは作ってみるまで正確な数値がわかりません。
そこで今回は、公式ドキュメントの記載と、実際に AWSコンソール上でルールを作成して検証した結果をもとに、カスタムルールの WCU の目安をまとめてみました。
国/地域
https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-geo-match.html
リクエスト元の国および地域を検査します。
国/地域の個数によらず、WCU は 1 です。
| 基本値 | WCU |
|---|---|
| 国/地域リスト | 1 |
リクエスト元の判定方法として以下の 2種類から選択できますが、どちらを選んでも WCU は変わりません。
- 送信元IPアドレス
- 任意のリクエストヘッダー (
X-Forwarded-Forなど) 中の IPアドレス
| オプション | WCU |
|---|---|
| 送信元アドレス | +0 |
| リクエストヘッダー中のアドレス | +0 |
IPアドレス
https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-ipset-match.html
リクエスト元の IPアドレスを検査します。
最大で 10,000個 の IPアドレスを紐付けられますが、どれだけ紐付けても WCU は 1 でした。
| 基本値 | WCU |
|---|---|
| IPアドレスリスト | 1 |
リクエスト元の判定方法は “国/地域” と同じ 2種類ですが、任意のヘッダーの場合、どの位置の IPアドレスを検査対象とするか指定できます。
- First
- Last
- Any
First または Last の場合には WCU は変わりませんが、Any の場合は +4 されます。
| オプション | WCU |
|---|---|
| First | +0 |
| Last | +0 |
| Any | +4 |
ASN
https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-asn-match.html
リクエスト元の IPアドレスが属する ASN (Autonomous System Number) を検査します。
ASN の個数によらず WCU は 1 です。
| 基本値 | WCU |
|---|---|
| ASNリスト | 1 |
ラベル
https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-label-match.html
評価チェーンの前方にあるルールによって付与されたラベルを検査します。
目的のラベルが付与されているかどうか、単一の値を指定できます。
WCU は 1 です。
| 基本値 | WCU |
|---|---|
| ラベル | 1 |
評価スコープとして以下の 2種類がありますが、WCU は変わりません。
- Label: ラベル完全一致
- Namespace: 名前空間 (
:区切り)
| オプション | WCU |
|---|---|
| Label | +0 |
| Namespace | +0 |
リクエスト構成要素
https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-fields-list.html
リクエストヘッダーやボディなど、HTTPリクエストの構成要素に対して検査できます。
構成要素やオプションによって WCU が変動します。
構成要素ごとの基本値
構成要素の WCU は基本的に 0 であり、評価方式 (文字列一致やサイズなど) によって WCU が加算される… と考えるとわかりやすいです。
ただし、一部の構成要素には WCU が課されます。
| 基本値 | WCU |
|---|---|
| HTTP メソッド | 0 |
| 単一ヘッダー | 0 |
| すべてのヘッダー | 0 |
| ヘッダーの順序 | 0 |
| Cookie | 0 |
| URI フラグメント | 0 |
| URI パス | 0 |
| JA3 フィンガープリント | 0 |
| JA4 フィンガープリント | 0 |
| クエリ文字列 | 0 |
| 単一クエリパラメータ | 10 |
| すべてのクエリパラメータ | 10 |
| 本文 | 0 |
| JSON 本文 | x2 |
単一クエリパラメータ:
クエリ文字列をパラメータごとにパースした、その特定の 1つのパラメータを検査します。
ドキュメントには記載がありませんが、WCU は 10 です。
すべてのクエリパラメータ:
特定のパラメータではなく、すべてのパラメータの値を対象に検査します。
ドキュメントに記載のとおり WCU は 10 です。
JSON 本文:
リクエストボディを JSON としてパースしたものを検査します。
これ自体の WCU は 0 なのですが、ステートメント本来の合計WCU が 2倍されます。
2倍となる範囲は単一のステートメントのみで、AND や OR で連結している他のステートメントには影響しません。
構成要素ごとのオプション
例えば “すべてのヘッダー” では、マッチングのスコープ (= ヘッダーのキーを見るのか? 値を見るのか?) や オーバーサイズ時の振る舞い (= 一致したと見なすか? そうでないか?) などを指定できますが、いずれも WCU に変化はありません。
| オプション | WCU |
|---|---|
| (構成要素により異なるが、いずれも) | +0 |
一致タイプ
評価方式として、文字列の一致やサイズの大小など、いくつかのタイプに分類できます。
各タイプの WCU は以下のように設定されています。
文字列
https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-string-match.html
与えられた値を文字列として評価します。
| 基本値 | WCU |
|---|---|
| 完全一致 | 2 |
| ○○で始まる | 2 |
| ○○で終わる | 2 |
| ○○を含む | 10 |
| 単語を含む | 10 |
| 正規表現 | 3 |
| 正規表現パターンセット | 25 |
単語を含む:
/[A-Za-z0-9_]+/ が単語として扱われます。
“○○を含む” と違い、行頭行末を含むこれ以外の文字が Delimiter として前後に存在する場合のみ検知されます。
正規表現:
https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-regex-match.html
正規表現パターンの長短や複雑さによらず、WCU は 3 となるようです。
“○○を含む” が 10 なので、WCU を少しでも抑えたい場合は正規表現を使うとよいかもしれません。
正規表現パターンセット:
複数のルールで使い回しができるように、任意の個数の正規表現パターンをセットにして名前をつけたものを正規表現パターンセットと呼びます。
セット中のパターン数によらず、WCU は 25 です。
サイズ
文字列のバイト数を評価します。
いずれも WCU は 1 です。
| 基本値 | WCU |
|---|---|
| 等しい | 1 |
| 等しくない | 1 |
| 以下 | 1 |
| 未満 | 1 |
| 以上 | 1 |
| 大きい | 1 |
攻撃
サイバー攻撃のシグネチャを検査します。
高負荷な処理となっているようで、WCU は大きめです。
| 基本値 | WCU |
|---|---|
| SQLインジェクション (Low) | 20 |
| SQLインジェクション (High) | 30 |
| XSS | 40 |
SQLインジェクション:
https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-sqli-match.html
検査の感度によって WCU が異なります。
Low は 20、High は 30 です。
XSS:
https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-xss-match.html
WCU は最も大きく、40 です。
テキスト変換
https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-transformation.html
対象を評価する際に、下処理として値を変換 (= 小文字化や各種デコードなどのプリセットされた変換関数を適用) することができます。
複数個の変換関数を適用できて、1つの変換ごとに WCU が 10 追加されます。
| オプション | WCU |
|---|---|
| 変換関数 (1つあたり) | +10 |
補足
テキスト変換は “JSON 本文” による WCU 2倍の範囲外となっています。
つまり、2倍されたあとに 10 が加算されます。
レート
https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-rate-based.html
HTTPリクエストの流入数に基づいてレートを制限します。
閾値や評価期間によらず、WCU は 2 です。
| 基本値 | WCU |
|---|---|
| レート | 2 |
リクエスト数をカウントする際の 集約キー を以下から選択できます。
- 送信元IPアドレス
- 任意のリクエストヘッダー中の IPアドレス
- すべて
- リクエスト構成要素やラベル、ASN に基づくカスタムキー
カスタムキーは任意の個数を設定できて、1つごとに WCU 30 が課されます。
各キーにはテキスト変換を適用することもできますが、リクエスト構成要素の検査の場合とは異なり、WCU は加算されません。
| オプション | WCU |
|---|---|
| 送信元アドレス | +0 |
| リクエストヘッダー中のアドレス | +0 |
| すべて | +0 |
| カスタムキー 1つあたり | +30 |
| ┗ テキスト変換 | +0 |
また、スコープダウン・ステートメント を用いて、カウント対象とするリクエストをフィルタすることができます。
スコープダウン・ステートメントにはこれまで述べてきた任意のステートメントを組み合わせて使用できます。
WCU は内包する構成ステートメントの総和となります。
| オプション | WCU |
|---|---|
| スコープダウンなし (すべてカウント) | +0 |
| スコープダウンあり | +(構成ステートメントの総和) |
補足
集約キーを “すべて” とした場合は、スコープダウン・ステートメントの使用が必須となります。
ルール共通
続いて、ステートメントによらないルールレベルでのオプションを見ていきます。
アクション
https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-action.html
ルール条件にマッチした際の WAF の処理内容を指定します。
| オプション | WCU |
|---|---|
| Allow | +0 |
| Block | +0 |
| Count | +0 |
| CAPTCHA | +0 |
| Challenge | +0 |
いずれも WCU は加算されませんが、CAPTCHA と Challenge には 追加料金 がかかります。
論理ステートメント
https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statements-logical.html
複数のステートメントを連結するための論理演算子です。
これ自体の WCU は 0 です。
| 基本値 | WCU |
|---|---|
| AND | 0 |
| OR | 0 |
| NOT | 0 |
カスタムリクエスト/レスポンス
https://docs.aws.amazon.com/waf/latest/developerguide/waf-custom-request-response.html
ルール条件にマッチした際、リクエストやレスポンスをカスタマイズできます。
いずれも WCU はかかりません。
| オプション | WCU |
|---|---|
| リクエスト | +0 |
| レスポンス | +0 |
ラベル付与
https://docs.aws.amazon.com/waf/latest/developerguide/waf-labels.html
ルール条件にマッチした際に、メタデータとしてラベルを付与できます。
付与されたラベルは後続のルールにおいて参照できます。
WCU はラベル 5つごとに 1 加算されます。
| オプション | WCU |
|---|---|
| ラベル (5つあたり) | +1 |
最適化
基本的に Protection pack (Web ACL) の総コストは各ルールの WCU の総和となりますが、ルールの組み合わせ次第では最適化が働いて WCU が割り引かれることがあります。
例えば以下のように、小文字に変換した URIパスに対して文字列の完全一致でチェックするルールを 2つ用意します。

各ルールの WCU は 文字列完全一致 (2) + テキスト変換 (10) = 12 となり、本来であればそれが 2つ分で Protection pack の総コストは 24 となるはずなのですが、

実際の結果は以下のとおり 14 となります。

以下のドキュメントに記載されているように、2つのルールで共通する “URIパスに対する小文字への変換処理” が最適化されて、テキスト変換のコスト計上が 1回分に抑えられたのでしょう。
https://docs.aws.amazon.com/waf/latest/developerguide/aws-waf-capacity-units.html
For example, if you define two rules to examine the same web request component, and the rules each apply a particular transformation to the component before inspecting it, AWS WAF might be able to charge you just once for applying the transformation.
WCU計算例
最後におさらいとして複雑なルールを組んでみて、その要素ごとの WCU を計算してみます。
ルールが長く、UI上では見づらいため、JSON にコメントを入れる形で記載します。[#n] でコメントした部分が実際に加算される WCU です。
{
"Name": "my-rule",
"Priority": 0,
"Statement": {
"RateBasedStatement": { // [#1] レートベースのチェック (WCU=2)
"Limit": 4649,
"AggregateKeyType": "CUSTOM_KEYS", // カスタムキーによる集約 (キーごとに +30)
"EvaluationWindowSec": 120,
"ScopeDownStatement": { // スコープダウン・ステートメント (内包するステートメントの総和が加算される)
"AndStatement": { // 論理ステートメントはコスト0
"Statements": [
{
"NotStatement": { // 論理ステートメントはコスト0
"Statement": {
"IPSetReferenceStatement": { // [#2] IPアドレスのチェック (WCU=1)
"ARN": "arn:aws:wafv2:us-east-1:123456789012:global/ipset/waf-test_ip_IPV4/123e4567-e89b-12d3-a456-426614174000",
"IPSetForwardedIPConfig": {
"HeaderName": "X-Forwarded-For",
"FallbackBehavior": "MATCH",
"Position": "ANY" // [#3] ヘッダー中の任意の位置 (WCU=4)
}
}
}
}
},
{
"RegexMatchStatement": { // [#4] 正規表現による文字列一致 (WCU=3)
"RegexString": "qqq",
"FieldToMatch": {
"SingleQueryArgument": { // [#5] 単一クエリパラメータ (WCU=10)
"Name": "p"
}
},
"TextTransformations": [
{
"Priority": 0,
"Type": "NONE"
}
]
}
},
{
"SqliMatchStatement": { // [#6] SQLインジェクション (感度High) のチェック (#7 の効果により本来の 2倍; WCU=60)
"FieldToMatch": {
"JsonBody": { // [#7] JSON本文 (WCU を 2倍)
"MatchPattern": {
"IncludedPaths": ["/a/b/c"]
},
"MatchScope": "ALL",
"OversizeHandling": "CONTINUE"
}
},
"TextTransformations": [ // [#8] テキスト変換 2つ (WCU=20)
{
"Priority": 0,
"Type": "COMPRESS_WHITE_SPACE"
},
{
"Priority": 1,
"Type": "HTML_ENTITY_DECODE"
}
],
"SensitivityLevel": "HIGH"
}
}
]
}
},
"CustomKeys": [ // [#9] 集約カスタムキー 2つ (WCU=60)
{
"Header": {
"Name": "h",
"TextTransformations": [ // カスタムキーの場合はテキスト変換のコスト0
{
"Priority": 0,
"Type": "LOWERCASE"
},
{
"Priority": 1,
"Type": "COMPRESS_WHITE_SPACE"
}
]
}
},
{
"UriPath": {
"TextTransformations": [
{
"Priority": 0,
"Type": "URL_DECODE"
},
{
"Priority": 1,
"Type": "NORMALIZE_PATH"
},
{
"Priority": 2,
"Type": "MD5"
}
]
}
}
]
}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "my-rule"
},
"Action": {
"Block": {
"CustomResponse": { // カスタムレスポンスはコスト0
"ResponseCode": 403,
"CustomResponseBodyKey": "waf-test-response",
"ResponseHeaders": [
{
"Name": "k",
"Value": "v"
}
]
}
}
},
"RuleLabels": [ // [#10] ラベル付与 5つ組 2セット (WCU=2)
{
"Name": "l1"
},
{
"Name": "l2"
},
{
"Name": "l3"
},
{
"Name": "l4"
},
{
"Name": "l5"
},
{
"Name": "l6"
}
]
}
#1 から #10 までで、合計 162 WCU です。
まとめ
以上、AWS WAF のカスタムルールにおける WCU値について、公式ドキュメントと検証をもとにステートメントの種類やルールのオプションごとの加算条件を整理しました。
主なポイントは以下のとおりです。
- 国/地域、IPアドレス、ASN、ラベルのチェックは基本的に WCU=1 と低コスト
- リクエスト構成要素のチェックは一致タイプによって変動し、文字列の完全一致で WCU=2、正規表現で WCU=3、“含む"検索で WCU=10、正規表現パターンセットで WCU=25
- 攻撃検知は高コストで、SQLインジェクションの感度Low が WCU=20、同High が WCU=30、XSS が WCU=40
- 単一/すべてのクエリパラメータは WCU=10
- JSON 本文は他の WCU を 2倍にする
- テキスト変換は 1つあたり WCU=10
- レートベースルールは基本 WCU=2 だが、カスタムキーは 1つあたり WCU=30 と高コスト
- 論理ステートメント、アクション、カスタムリクエスト/レスポンスは WCU=0
- ラベル付与は 5つあたり WCU=1
- 共通処理の最適化により、単純な総和よりも WCU が割り引かれることがある
カスタムルール作成前の見積もりの参考にしていただければ幸いです。
今後ともよろしくお願い申し上げます。
