AWS WAFのレートベースルールで特定のIPアドレスとパスを除外する

AWS WAFで特定IPと特定パス以外にレートベースルールを適用してみました。
2021.07.07

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

AWS WAFのレートベースルールは、特定のIPアドレスからのリクエストをカウントし、制限を超えると通信を一時的にブロックします。本記事では、図の塗りつぶし部分にあたる、特定IPと特定パス以外にレートベースルールを適用します。

IPセットの作成

東京リージョンにIPsetを登録します。

正規表現パターンセットの作成

特定のパスや画像ファイルを対象にしました。

レートベースルールを作成

ルールを作成します。Web ACL>Add rule>Add my own rules and rule groups>rule builder>Rule JSON editorでJSONエディターを開き、以下をペーストします。ARNは適宜変更してください。レートベースルールのしきい値は100です。ScopeDownStatementでIPSetのNotとURI path正規表現マッチのNOTのANDを指定してます。

{
  "Name": "Rate-base",
  "Priority": 1,
  "Statement": {
    "RateBasedStatement": {
      "Limit": 100,
      "AggregateKeyType": "IP",
      "ScopeDownStatement": {
        "AndStatement": {
          "Statements": [
            {
              "NotStatement": {
                "Statement": {
                  "IPSetReferenceStatement": {
                    "ARN": "arn:aws:wafv2:ap-northeast-1:1234567890123:regional/ipset/IPset/123a4b56-7890-12cc-3456-b78901234567890"
                  }
                }
              }
            },
            {
              "NotStatement": {
                "Statement": {
                  "RegexPatternSetReferenceStatement": {
                    "ARN": "arn:aws:wafv2:ap-northeast-1:1234567890123:regional/regexpatternset/ignore_path_list/4123a4b56-7890-12cc-3456-b78901234567890",
                    "FieldToMatch": {
                      "UriPath": {}
                    },
                    "TextTransformations": [
                      {
                        "Priority": 0,
                        "Type": "NONE"
                      }
                    ]
                  }
                }
              }
            }
          ]
        }
      }
    }
  },
  "Action": {
    "Block": {}
  },
  "VisibilityConfig": {
    "SampledRequestsEnabled": true,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "Rate-base"
  }
}

テスト

固定レスポンスを返すALBを作成し、AWS WAFに割当てました。ALBはHelloというレスポンスを返します。

スクリプト

ALBに150回接続を行うスクリプトを用意しました。内容は以下の通りです。

#!/bin/sh

URL="http://testalb-1234567890.ap-northeast-1.elb.amazonaws.com/"; 
#URL="http://testalb-1234567890.ap-northeast-1.elb.amazonaws.com/test/image.jpeg";
HEAD="Content-Type:text/xml"; 

for i in {0..150}
do
    curl -H $HEAD $URL
    echo ""
    echo ${i}
    sleep 0.1
done

トップページに接続すると、Helloという応答が返ります。100回のしきい値を越えても20秒〜30秒程度はレスポンスが返ってきて、しばらくすると403になりました。

$ sh curl_loop.sh
Hello
0
Hello
1
(略)
Hello
149
Hello
150
$ sh curl_loop.sh
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
</body>
</html>

0
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
</body>
</html>

ブラウザで接続しても、トップページは403になります。

除外パスに登録された/gazo.jpegはアクセスできます。

確認をした結果、除外パスにはなんど接続しても接続できました。また、除外パスに何回接続してもレートベースルールではカウントされないためか、トップページへのアクセスは許可されました。画像ファイルや特定のパス、システム連係を行うIPを除外したいケースで役立つと思います。