AWS WAFにてデフォルトAllowで「特定のIPリスト以外をBlock」する [Terraform]

まれなパターン
2022.01.20

ちゃだいん(@chazuke4649)です。

AWS WAFのIPリストは「ホワイトリストをAllow」「ブラックリストをBlock」がよくあるパターンですが、今回は「ホワイトリスト以外をBlock」です。(「ブラックリスト以外をAllow」はまた今度)

概要

一般的なIPリストの制限はホワイトリスト(許可したいIPリスト)を許可する or ブラックリスト(拒否したいIPリスト)をブロックするといった方法です。これらを設定する際にはルールの流れは以下の通りです。

ホワイトリストの通常パターン

  • 1)ホワイトリストをAllow
  • デフォルトBLock

ブラックリストの通常パターン

  • 1)ブラックリストをBlock
  • デフォルトAllow

ただし、他のルールとの都合上、デフォルトのアクションを変えたい場合があります。

例えば、サードパーティベンダーのマネージドルールを併用したいなど。マネージドルールは攻撃可能性ありの条件とマッチしたトラフィックをCountやBlockし、それ以外のトラフィックをallowとする必要があります。その場合、ホワイトリスト運用は以下のようにする必要があります。

ホワイトリストの通常じゃないパターン

  • 1)ホワイトリスト以外をBlock
  • 2)マネージドルールでBlock
  • デフォルトAllow

これを行う上で、「ホワイトリスト以外をBlock」というルールの記述に少しハマったので、結果どうしたかを紹介したいと思います。

通常パターン「ホワイトリストをAllowする方法」は以下ブログをご覧ください。

ホワイトリスト以外をBlockする(マネジメントコンソール)

AWS WAFコンソールより新しくWAF Web ACLを作成します。

※ 通常パターンとの差分箇所以外は割愛します

Step1では任意の名前やリソースタイプ(CloudFront or not)を選択します。

Step2が本題です。

  • 通常パターンではRule typeでIP setを選びますが、今回はRule builderを選びます
  • 名前はBlockIpsExceptWhitelitsとします
  • TypeはRegular ruleを選びます

次に、ここがポイントですが 「doesn't match the statement (NOT)」 を選びます。

  • If a request: doesn't match the statement (NOT)
  • Inspect: Originates from an IP address in
  • IPset: (ここですでに作成したホワイトリストなIPリストを選択)
  • IP address to use as the originating address: Source IP address
  • Action: Block

Rulesの追加が終わったら、Default actionは Allow を選びます。

あとは、ウィザードにし従って他設定を完了させればOKです。

ちなみにルールをJSONで表示すると以下の通りです。

{
  "Name": "BlockIpsExceptWhitelist",
  "Priority": 0,
  "Statement": {
    "NotStatement": {
      "Statement": {
        "IPSetReferenceStatement": {
          "ARN": "arn:aws:wafv2:us-east-1:111122223333:global/ipset/myips/xxxx-xxxx-xxxx-example"
        }
      }
    }
  },
  "Action": {
    "Block": {}
  },
  "VisibilityConfig": {
    "SampledRequestsEnabled": true,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "BlockIpsExceptWhitelist"
  }
}

ホワイトリスト以外をBlockする(Terraform)

Terraformで作成する場合だと、以下の通りです。

waf.tf

resource "aws_wafv2_web_acl" "test" {
  provider = aws.virginia
  name     = "test-waf"
  scope    = "CLOUDFRONT"
  default_action {
    allow {}
  }

  rule {
    name = "BlockIpsExceptWhitelist"
    priority = 1
    statement {
      not_statement {
        statement {
          ip_set_reference_statement {
            arn = "arn:aws:wafv2:us-east-1:111122223333:global/ipset/myips/xxxx-xxxx-xxx-example"
          }
        }
      }
    }
    action {
      block {}
    }
    visibility_config {
      cloudwatch_metrics_enabled = true
      metric_name                = "BlockIpsExceptWhitelist"
      sampled_requests_enabled   = true
    }
  }

  visibility_config {
    cloudwatch_metrics_enabled = true
    metric_name                = "test-waf-webacl"
    sampled_requests_enabled   = true
  }
}

終わりに

ほとんどの場合は通常パターンでいけると思いますが、マネージドルールと組み合わせる場合等に利用ご検討ください。

それではこの辺で。ちゃだいん(@chazuke4649)でした。