0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TerraformでALB+WAFによる同一IPによるアクセス数制御の構築

Posted at

前書き

Webサービスの運用において、特定のIPアドレスからの過剰なアクセスは、サービスのパフォーマンス低下や不正アクセスの温床となる恐れがあります。特に公開APIWebアプリケーションでは、短時間に大量のリクエストを送信する悪意あるユーザーやボットへの対策が不可欠です。

本記事では、AWSのApplication Load Balancer(ALB)Web Application Firewall(WAF) を組み合わせ、Terraformを用いてインフラをコードで構築する方法を記載します。

AWS WAF

概要

Webアプリケーションへの 悪意のあるアクセス(不正リクエスト) をブロックしたり制御したりできるサービス。
例えば、SQLインジェクション(データベースへの不正な命令)やクロスサイトスクリプティング(XSS)などの攻撃を防ぐ。

Webアプリケーションが配置されている以下のAWSリソースに組み込んで使う

たとえば、以下のような不正アクセスを防ぐことができる

  • Webサイトに対する 攻撃(例:SQLインジェクション)
  • 特定のIPアドレスからの 不審なアクセス
  • 短時間に大量のリクエストを送る ボットやDDoS攻撃
  • 特定の国や地域からのアクセス制限

主な制御機能

IPアドレスの制御

  • 特定のIPアドレスまたはIP範囲を、許可(Allow)または遮断(Block) できる
    (例:海外IPからのアクセスを遮断したい場合等に行う)

リクエストの内容による制御

  • リクエストの中の情報(ヘッダー、URI、クエリ文字列、ボディなど)を条件にできる
    (特定のURLパターンへのアクセスを制限する)

SQLインジェクション対策

  • 入力フォームなどから送られるデータに SQL文のような不審な文字列 が含まれているか検査してブロック

クロスサイトスクリプティング(XSS)対策

  • 悪意あるスクリプトがWebページに埋め込まれるのを防ぐ

レートベースの制御(Rate-based rules)

  • 一定時間内に同じIPアドレスから異常に多くのリクエストが来た場合にブロック

例:DDoS(分散型サービス拒否)対策の一部として使える。

地理的な制御(Geo match)

  • アクセス元の国や地域を指定して制御できる

カスタムルールの作成

  • 独自の条件を組み合わせて、柔軟なルールを作れる
    (例:「特定のパスに対してPOSTメソッドかつUser-Agentが○○のときだけブロック」など)

構築の際の前提条件

  • Terraformの環境がある
  • Terrformにて、ALBの構築が完了済み

構築内容

Terraformの設定内容

# WAFの設定
resource "aws_wafv2_web_acl" "alb_waf_acl" {
  name        = # 任意の名前 入力例:"alb-waf"
  scope       = "REGIONAL"
  
  default_action {
    allow {}
  }

  rule {
    name     = # 任意の名前 入力例: "limit-50-requests-per-second"
    priority = 1
    action {
      block {}
    }

    statement {
      rate_based_statement {
        # 15000 req / 5分 ≒ 平均 50 req/sec
        limit              = 15000
        aggregate_key_type = "IP"
      }
    }

    visibility_config {
      cloudwatch_metrics_enabled = true
      metric_name                = # 任意の名前 入力例: "limit-50-requests-per-second"
      sampled_requests_enabled   = true
    }
  }

  visibility_config {
    cloudwatch_metrics_enabled = true
    metric_name                = # 任意の名前 入力例: "alb-waf-acl"
    sampled_requests_enabled   = true
  }
}

# ALBにWAFを関連付ける
resource "aws_wafv2_web_acl_association" "alb_waf_attach" {
  resource_arn = # albのarnを記述する
  web_acl_arn  = aws_wafv2_web_acl.alb_waf_acl.arn
}

メソッドと説明

aws_wafv2_web_aclで使用したメソッドと説明

メソッド 説明
name WAF(Web ACL)の名前を設定する。WAFをTerraformやAWS管理画面で識別しやすくするために付けるラベル。任意の文字列で良い。
scope WAFをどこに適用するかを指定する。REGIONALを指定すると、ALBなどのリージョンサービスに適用される。CloudFrontの場合は CLOUDFRONT を使う。

default_actionで使用したメソッドと説明

すべてのルールに一致しなかったリクエストに対する最終処理を指定する。

メソッド 説明
allow {} 一致しなかったリクエストを許可する
block {} ※ 今回は未使用)一致しなかったリクエストをブロックする

他にできる設定

  • count {} を使うと、リクエストを記録するだけで実際にはブロックしないテスト運用ができる

ruleで使用したメソッドと説明

1つのWAFルールを定義する。複数記述することで複数の対策が可能になる。

メソッド 説明
rule 1つのWAFルールを定義する。複数記述することで複数の対策が可能になる
name このルールの識別名。任意のわかりやすい名前をつける
priority ルールの優先順位を数字で指定する。小さいほど優先される
action このルールに一致した場合の動作を指定する
block {} 一致したリクエストをブロックする
allow {} ※ 今回は未使用)一致したリクエストを許可する
count {} ※ 今回は未使用)一致したリクエストを記録のみする

他にできる設定

  • override_action を使えば、マネージドルール使用時にアクションを上書きできる

statementで使用したメソッドと説明

ルールの対象条件(どんなリクエストに適用するか)を設定する

メソッド 説明
rate_based_statement 一定期間内のリクエスト数が閾値を超えたIPを対象にする設定
limit 一定期間内の最大リクエスト数を指定する(今回は、5分間で15,000回のアクセス数制御にしている)
aggregate_key_type 集計の基準を指定する。IPにする事で、IPアドレスごとにカウントする

他にできる設定

  • byte_match_statement(文字列一致)
  • geo_match_statement(国別制限)
  • ip_set_reference_statement(IPリスト)
  • regex_pattern_set_reference_statement(正規表現マッチ)
  • size_constraint_statement(リクエストサイズ制限)

他にも制御できる項目がある為、公式ドキュメントを参照する

1回目で使用したvisibility_configのメソッドと説明

ルールごとに、どれくらいそのルールが発動したかをCloudWatchで確認できるようにするための設定。分かりやすく言うと、「このルールが何回ブロックしたか」などを可視化するための設定。

メソッド 説明
cloudwatch_metrics_enabled = true CloudWatchにメトリクス(統計情報)を送信する設定
metric_name CloudWatchに表示されるメトリクスの名前を指定する
sampled_requests_enabled = true 実際にWAFが検知したリクエストを一部CloudWatchに記録する設定

2回目で使用したvisibility_configのメソッドと説明

WAF全体としてのリクエスト状況をCloudWatchで把握するための設定。

メソッド 説明
cloudwatch_metrics_enabled = true WAF全体に対してCloudWatchにメトリクスを送る設定
metric_name WAF全体用のメトリクス名を指定する
sampled_requests_enabled = true 全体で検知したリクエストの一部を記録する設定

visibility_configが2回記載してある理由

WAFは、ルールごと全体 でそれぞれモニタリングため、2箇所で設定を行っている

visibility_config の場所 監視対象 目的
WAF本体(最上位) Web ACL全体 全体のリクエスト・メトリクスをCloudWatchで確認する為に設定
rule ルール個別 各ルールの発動状況や効果を確認する為に設定

visibility_configのCloudWatchの設定の注意点

注意点

  • visibility_config をTerraformに書くだけでは、CloudWatch Logs にログが出力されない
  • 別途、CloudWatch Logs用のロググループと、WAFログ出力設定(aws_wafv2_web_acl_logging_configuration)の定義が必要
  • 運用時には metric_name とロググループ名を対応付けておくと「障害対応」や「問題解決」が容易になる
  • aws_wafv2_web_acl_logging_configurationのサンプルコードは下記に記載
# CloudWatch Logsのロググループを作成
resource "aws_cloudwatch_log_group" "waf_logs" {
  name              = "/aws/waf/alb-waf-logs"
  retention_in_days = 30
}

# WAFログ設定(ACLとLogGroupを紐付け)
resource "aws_wafv2_web_acl_logging_configuration" "example" {
  log_destination_configs = [
    aws_cloudwatch_log_group.waf_logs.arn
  ]

  resource_arn = aws_wafv2_web_acl.example.arn
}

参考資料

感想

今回、WAFを導入したことで、WAFの設定箇所について理解できました。しかし、今回はアクセス数の制御目的でWAFを導入したため、WAF本来のセキュリティ機能に関する設定はあまり行えていません。今後は、WAFで設定可能な機能を把握し、案件に応じて効果的に活用できるようにしたいと思います。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?