WAFでブロックしたメトリクスを通知するCloudWatchアラームをAWS CLIで作成してみた

記事タイトルとURLをコピーする

2022年新卒入社で現在CS課のOJTを受けている(た)末廣です。 AWS WAFでブロックした攻撃を一定の条件の元、通知を発生させたいという目的で 調査、検証する機会がありましたのでブログにまとめます。

概要

AWS WAF は、Amazon CloudFront、Application Load Balancer (ALB) 上で動作する AWS の提供するクラウド型 WAF のサービスです。 aws.amazon.com

WAFは、あらかじめルールとして設定しておいた問題がある通信は遮断されるため、リソースの管理者は攻撃に気づくことができません。 ブロックすることができているため、攻撃に対して何か対処する必要はありませんが、そもそも攻撃には気づきたい場合は何かしら別の機能を利用する必要があります。

今回は、CloudWatchアラームとAmazon SNSを組み合わせることで、その仕組みを作成しました。 CloudWatchでWAFをモニタリングし、ブロックしたメトリクスがある条件のもと通知するアラームをAWS CLIで作成します。 本検証でのアラームの発生条件は、WAFが関連付けられているリソースへの全てのルールに対するブロックの合計数が設定値を超過した時に通知するものになります。

検証内容

実際調査、検証した内容を順に記載していきます。

WAFの作成

WAFの作成はこちらのブログを参考にしています。関連付けるリソースとしてALBを同様に使用しています。 blog.serverworks.co.jp

CloudWatchではルールごとにメトリクスを作成するので、全てのルールにチェックを付けてしまいましょう。どのメトリクスを使用するかはアラームを作成する時に決めます。 今回作成したルールは優先度の高い順から

  • 自宅ののIPアドレスのIPセットからの通信をブロック
  • あるEC2インスタンスに紐付いているEIPのIPセットからの通信をブロック
  • 日本からの通信をブロック
  • 「attack」という文字列を含んだリクエストをブロック(図にはありませんが後に追加しました)

といったものになります。

ルールごとのメトリクスの作成

CloudWatch アラームの作成

もちろんマネジメントコンソールからでも作成できますが、CLIの方がより細かな設定ができるため、CLIで作成したものを紹介します。

CLIでアラームを作成

CLIでアラームを作成していきます。コマンドはput-metric-alarmを使用します。

docs.aws.amazon.com

必要なパラメータの数が多いので、オプションを付けての実行ではなく、JSON形式で作成したものを引き渡します。

docs.aws.amazon.com

このドキュメントの使用例を参考にし、以下の条件の元作成したものです。

  • 通知先にSNSのARNを指定
  • 全てのルールの合計値を表す "ALL" メトリクスをターゲットに指定
  • 通信のブロック数の合計が1分間で5回以上を超過すればアラーム発生
{
    "AlarmName": "ojt-trial-cs-alarm-all-cli",
    "AlarmDescription": "WAFの全てのメトリクスアラーム",
    "AlarmActions": [
        "arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:waf-trial"
    ],
    "ComparisonOperator": "GreaterThanOrEqualToThreshold",
    "EvaluationPeriods": 1,
    "DatapointsToAlarm": 1,
    "Threshold": 5,
    "Metrics": [
        {
            "Id": "all",
            "MetricStat": {
                "Metric": {
                    "MetricName": "BlockedRequests",
                    "Namespace": "AWS/WAFV2",
                    "Dimensions": [
                      {
                          "Name": "WebACL",
                          "Value": "ojt-trial-cs-waf-acl"
                      },
                      {
                          "Name": "Region",
                          "Value": "ap-northeast-1"
                      },
                      {
                          "Name": "Rule",
                          "Value": "ALL"
                      }
                    ]
                },
                "Period": 60,
                "Stat": "Sum"
            }
        }
    ]
}

JSONファイルとして保存し、CLIコマンドで実行します。実行する際はfile://を忘れないように注意する必要があります。

$ aws cloudwatch put-metric-alarm --cli-input-json file://ojt_trial_cs_alarm.json

これでCloudWatchアラームを作成することができました。

アラームを発生させる

作成したCloudWatchアラームを発生させます。SNSの通知先に設定したアドレスにメールが届き、正常にアラームが発生したことが確認できました。 7件の通知のブロックがメトリクスに表示されていることもCloudWatchで見ることができます。

SNSから通知の受信

メトリクスの様子

アラーム作成のおまけ

あるリソースへの攻撃に対するアラームの発生を作成は以上の設定で問題ないですが、 一部の特定のルールのメトリクスの合計値のみをターゲットとして利用する、など より詳細なアラームの発生条件を指定したい場合は CLIで使用したJSONファイルを以下のように修正します。 WAFのルールの指定方法を "ALL" として一つ作成するのではなく、それぞれルールごとに作成し、合計値をアラームの発生条件としています。

{
    "AlarmName": "ojt-trial-cs-alarm-cli",
    "AlarmDescription": "WAFのACLごとの合計メトリクス",
    "AlarmActions": [
        "arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:waf-trial"
    ],
    "ComparisonOperator": "GreaterThanOrEqualToThreshold",
    "EvaluationPeriods": 1,
    "DatapointsToAlarm": 1,
    "Threshold": 5,
    "Metrics": [
        {
            "MetricStat": {
                "Metric": {
                    "MetricName": "BlockedRequests",
                    "Namespace": "AWS/WAFV2",
                    "Dimensions": [
                      {
                          "Name": "WebACL",
                          "Value": "ojt-trial-cs-waf-acl"
                      },
                      {
                          "Name": "Region",
                          "Value": "ap-northeast-1"
                      },
                      {
                          "Name": "Rule",
                          "Value": "ojt-trial-cs-waf-rule-myip-block"
                      }
                    ]
                },
                "Period": 60,
                "Stat": "Sum"
            },
            "Id": "m1",
            "ReturnData": false
        },
        {
            "MetricStat": {
                "Metric": {
                    "MetricName": "BlockedRequests",
                    "Namespace": "AWS/WAFV2",
                    "Dimensions": [
                      {
                          "Name": "WebACL",
                          "Value": "ojt-trial-cs-waf-acl"
                      },
                      {
                          "Name": "Region",
                          "Value": "ap-northeast-1"
                      },
                      {
                          "Name": "Rule",
                          "Value": "ojt-trial-cs-waf-rule-eip-block"
                      }
                    ]
                },
                "Period": 60,
                "Stat": "Sum"
            },
            "Id": "m2",
            "ReturnData": false
        },
        {
            "MetricStat": {
                "Metric": {
                    "MetricName": "BlockedRequests",
                    "Namespace": "AWS/WAFV2",
                    "Dimensions": [
                      {
                          "Name": "WebACL",
                          "Value": "ojt-trial-cs-waf-acl"
                      },
                      {
                          "Name": "Region",
                          "Value": "ap-northeast-1"
                      },
                      {
                          "Name": "Rule",
                          "Value": "ojt-trial-cs-waf-rule-japan-block"
                      }
                    ]
                },
                "Period": 60,
                "Stat": "Sum"
            },
            "Id": "m3",
            "ReturnData": false
        },
        {
            "MetricStat": {
                "Metric": {
                    "MetricName": "BlockedRequests",
                    "Namespace": "AWS/WAFV2",
                    "Dimensions": [
                      {
                          "Name": "WebACL",
                          "Value": "ojt-trial-cs-waf-acl"
                      },
                      {
                          "Name": "Region",
                          "Value": "ap-northeast-1"
                      },
                      {
                          "Name": "Rule",
                          "Value": "ojt-trial-cs-word-attack-block"
                      }
                    ]
                },
                "Period": 60,
                "Stat": "Sum"
            },
            "Id": "m4",
            "ReturnData": false
        },
        {
            "Id": "error_total",
            "Expression": "m1+m2+m3+m4",
            "ReturnData": true
        }
    ]
}

このようにアラームを作成すると、アラームの原因となるルールがアラームのメトリクス上から詳細に確認することができる上、より詳細に検知したいルールを設定することができます。

修正後アラームのメトリクスの様子

また、下図のようにマネジメントコンソールからも同様に合計値をアラームとして作成することができますが、メトリクスを選択するフェーズで、まだ一度も発生していないルールに関するメトリクスが表示されないので、ルールに対する通信を一度実行するか、今回紹介したCLIからの作成を試す必要があると思います。

マネジメントコンソールからのアラームの作成

まとめ

AWS WAFでは攻撃をブロックすることができているため、実際に何かしら影響が出ているわけではないので、対処する必要はないかもしれません。 それが故に、攻撃を受けている事自体も気づく事もできません。 今回作成したアラームによってパフォーマンス、セキュリティが向上するといったことはありませんが、 バトル漫画ではかっこいいように見える「何か攻撃でもしたか?」という現実ではあまり気持ちが良くない状態を解決はできるのではないかと思います。

末廣 満希(執筆記事の一覧)

2022年新卒入社です。ここに何かかっこいい一言を書くことができるエンジニアになれるように頑張ります。