いわさです。
AWS WAF にはレートベースルールというものがあって、同一条件のリクエストが一定期間の間に指定回数以上を超えた場合に検出あるいはブロックなどを行うことが出来ます。
以前は同一の IP アドレスからという条件のみだったのですが、ここ 1 年くらいで IP アドレス以外の任意の条件をベースにルールを設定出来るようになりました。
ただし、この一定回数以上というレートを評価する期間については直近 5 分間という固定の期間で、カスタマイズが出来ませんでした。
What's New AWS のアナウンスがまだ出ていないですが、AWS WAF の公式ドキュメントによるとこの期間がカスタマイズ出来るようになったようです。
この期間カスタマイズしたい時あるなーと思っていたので、これは!と思い確認してみることにしました。
2024.03.05 追記
What's New でもアナウンスされました。
レートベースルール設定項目に「Evaluation window」が追加されている
早速ルールを作成してみたところ、レートベースルールの設定項目に新たに「Evaluation window」という項目が追加されています。
こちらでカスタマイズ出来るみたいです。
設定可能な値は従来の 5 分間に加えて、1 分間と 2 分間、あとはさらに長い 10 分間が設定出来るようなりました。
この中から選択する形ですね、任意の時間を入力出来るわけではありません。まぁでも良いですね!
やってみた
今回は 1 分間に 100 回というレートベースルールを作成して評価してみました。
リクエスト元は同一クライアントから行おうと思っているので、条件は IP アドレスあたりで良いでしょう。
今回は東京リージョンに適当な API Gateway を作成し、レートベースルールを設定した Web ACL を関連付けしました。
こいつに対して 1 分以内に同一クライアントから大量のリクエストを送信してやればレートリミットエラーが発生し、従来と異なり 5 分待たずにレートリミットが解消されるはずです。
リクエスト送信はおなじみの Apache Bench を使います。
まずは 100 回リクエストを送信します。
% ab -n 100 -c 1 https://o8u7dlv92g.execute-api.ap-northeast-1.amazonaws.com/hoge0301api
This is ApacheBench, Version 2.3 <$Revision: 1903618 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking o8u7dlv92g.execute-api.ap-northeast-1.amazonaws.com (be patient).....done
Server Software:
Server Hostname: o8u7dlv92g.execute-api.ap-northeast-1.amazonaws.com
Server Port: 443
SSL/TLS Protocol: TLSv1.2,ECDHE-RSA-AES128-GCM-SHA256,2048,128
Server Temp Key: ECDH X25519 253 bits
TLS Server Name: o8u7dlv92g.execute-api.ap-northeast-1.amazonaws.com
Document Path: /hoge0301api
Document Length: 1324 bytes
Concurrency Level: 1
Time taken for tests: 19.113 seconds
Complete requests: 100
Failed requests: 0
Total transferred: 153600 bytes
HTML transferred: 132400 bytes
Requests per second: 5.23 [#/sec] (mean)
Time per request: 191.126 [ms] (mean)
Time per request: 191.126 [ms] (mean, across all concurrent requests)
Transfer rate: 7.85 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 109 138 38.1 119 338
Processing: 31 53 27.3 42 161
Waiting: 31 53 27.3 42 160
Total: 146 191 47.0 169 440
Percentage of the requests served within a certain time (ms)
50% 169
66% 215
75% 232
80% 237
90% 245
95% 252
98% 324
99% 440
100% 440 (longest request)
その後に、何でも良いですが同一 IP アドレスからリクエストを送信します。
% curl https://o8u7dlv92g.execute-api.ap-northeast-1.amazonaws.com/hoge0301api/pets -i
HTTP/2 403
date: Thu, 29 Feb 2024 23:20:58 GMT
content-type: application/json
content-length: 23
x-amzn-requestid: 08beb518-c0b1-4676-a8bf-02b0cd04d70f
x-amzn-errortype: ForbiddenException
x-amz-apigw-id: T6-mQGk6tjMEBQg=
{"message":"Forbidden"}
403 Forbidden
がレスポンスされましたね。レートリミットが作動してそうです。良さそう。
次に、数十秒時間を置いてまたリクエストを送信してみます。これまでは 5 分待つ必要がありましたがどうかな。
% curl https://o8u7dlv92g.execute-api.ap-northeast-1.amazonaws.com/hoge0301api/pets -i
HTTP/2 200
date: Thu, 29 Feb 2024 23:21:36 GMT
content-type: application/json
content-length: 184
x-amzn-requestid: 1a70c735-78c7-4ff0-b6fc-82d654bbf4c5
access-control-allow-origin: *
x-amz-apigw-id: T6-sJFLONjMEl6A=
x-amzn-trace-id: Root=1-65e11180-6219b5de59923c1e1c4ccef2
[
{
"id": 1,
"type": "dog",
"price": 249.99
},
{
"id": 2,
"type": "cat",
"price": 124.99
},
{
"id": 3,
"type": "fish",
"price": 0.99
}
]
正常にレスポンスが返ってきました。評価期間がうまく動いていますね。
さいごに
本日は AWS WAF のレートベースルールの期間を選択出来るようになったので、5 分から 1 分に変更してリミット到達前後の挙動を観察してみました。
攻撃対策としてだと 5 分とかでも良いと思うのですが、私の場合は API Gateway のスロットリングの代わりに AWS WAF のレートベースルールを使ってスロットリングを実装したい時がたまにあって、5 分だと長過ぎるなぁと思うことがありました。
1 分とかで設定出来るようになったのでより柔軟にレートベースルールを導入しやすくなったのではないでしょうか。