4
4

More than 1 year has passed since last update.

AWS WAFで海外からのアクセスのみルールを適用する

Posted at

やりたいこと

海外からのアクセスのみWAFのルールを適用する
言い換えると
日本からのアクセスは通信を通すようにする

なぜやるか

アプリケーション内での検索クエリがsqlインジェクションルールに引っかかり弾かれてしまった
sqlインジェクションルールの詳細がブラックボックスになっているため、
穴を開ける形を取らないといけなくなった。
国内限定で使うアプリケーションなので海外からのアクセスにのみWAFを適用することにした。

前提

今回適用するルールは

  • 日本からの通信か(allow)
  • sqlインジェクション(block)
  • レートベースルール(block)

albにアタッチするところまではやらない

コード

main.tf
#----------------------------
# WAF ACL
#----------------------------
resource "aws_wafv2_web_acl" "main" {
  name  = "${var.app_name}-WebACL"
  description = "${var.app_name}-WebACL"
  scope = "REGIONAL"

  default_action {
    allow {}
  }

  # 日本からの通信に関しては通信を通し、日本以外からのアクセスは後続のルールが適用される
  rule {
    name     = "allowJpRule"
    priority = 0

    action {
      allow {}
    }
    statement {
      geo_match_statement {
        country_codes = ["JP"]
      }
    }
    visibility_config {
      cloudwatch_metrics_enabled = true
      metric_name                = "allowJpRuleMetric"
      sampled_requests_enabled   = false
    }
  }

  #DDoS攻撃に対するルール(5分間あたりのlimit(閾値)を超えた場合にblockする)
  rule {
    name     = "AWSRateBasedRule"
    priority = 10

    action {
      block {}
    }

    statement {
      rate_based_statement {
        limit = 300
        aggregate_key_type = "IP"
      }
    }
    visibility_config {
      cloudwatch_metrics_enabled = true
      metric_name                = "AWSRateBasedRuleWAFMetric"
      sampled_requests_enabled   = false
    }
  }

  #SQLインジェクション攻撃に対するルール
  rule {
    name     = "AWSManagedRulesSQLiRuleSet"
    priority = 20

    override_action {
      none {}
    }

    statement {
      managed_rule_group_statement {
        name        = "AWSManagedRulesSQLiRuleSet"
        vendor_name = "AWS"
      }
    }
    visibility_config {
      cloudwatch_metrics_enabled = true
      metric_name                = "AWSManagedRulesSQLiRuleSetWAFMetric"
      sampled_requests_enabled   = false
    }
  }

  visibility_config {
    cloudwatch_metrics_enabled = true
    metric_name                = "${var.app_name}-WebACL"
    sampled_requests_enabled   = false
  }
}

ポイント

.tf
# 日本からの通信に関しては通信を通し、日本以外からのアクセスは後続のルールが適用される
  rule {
    name     = "allowJpRule"
    priority = 0

    action {
      allow {}
    }
    statement {
      geo_match_statement {
        country_codes = ["JP"]
      }
    }
    visibility_config {
      cloudwatch_metrics_enabled = true
      metric_name                = "allowJpRuleMetric"
      sampled_requests_enabled   = false
    }
  }

priority = 0

こうすることで一番最初に実行される

action {
 allow {}
}

こうすることで通信を通すということになるので
JPからのアクセスは後続のルールを適用せずに通信を通すということができる。

補足

ルール内で追加の条件を書くこともできるが
terraformがand_statementor_statement内での
rate_based_statement managed_rule_group_statementをサポートしていなかったため(2022/02/07)
別でルールを適用する必要があった。
ので
今回のような形になった。

素朴な疑問

これ作ってみて思ったことは、

国内限定で使用することが前提のアプリケーションの場合
海外からのアクセスは完全に断ち切ればいいのでは?
金額も安く済みますし😅

と思いました。
何かデメリットとかるのでしょうかね。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4