CloudTrailでWAF IP setの操作を見える化し、期限付き自動解除も実装した話

こんにちは、L小川です。

皆さんはWAFを使ってますか?
Webアプリケーションを運用するうえで、WAFはセキュリティ対策の要のひとつです。
WAFには不正アクセスを自動でブロックする機能もありますが、過去の記事でご紹介したように、弊社ではWAFの検知情報をもとに手動でIPアドレスをブロックする運用も行っています。
手動でブロックする場合、誰が・いつ・どのIPをブロック(解除)したか、把握できていますか?

この記事では、AWS CloudTrailをトリガーにAWS WAFのIPブロック・解除操作を記録・通知する仕組みを紹介します。

システム構成:初期バージョン

今回構築した仕組みは、WAFのIP Setへの操作をCloudTrailで検知し、「誰が・いつ・どのIPを・ブロック/解除したか」をDynamoDBに記録し、Slackへ通知するものです。

使用するAWSサービスは以下のとおりです。

  • AWS WAF :IPブロック・解除の操作対象
  • AWS CloudTrail :WAF操作イベントの検知・証跡のS3保存
  • Amazon S3 :CloudTrail証跡ログの保存先
  • Amazon EventBridge :Lambdaのトリガー
  • AWS Lambda :記録・通知の処理
  • Amazon DynamoDB :操作履歴の保存

全体の構成は以下のとおりです。

WAF操作通知のシステム構成概要図

CloudTrail

「証跡」を作成し、「書き込み」のAPIアクティビティのみを記録するようにします。

AWS CloudTrail 証跡作成画面キャプチャ

証跡の作成にあたり、証跡ログを保存するS3バケットの指定が必要になります。今回はWAFのIP set変更を検知するための証跡ログであり、長期間保存する必要はないのでS3のライフサイクルフックで1日のみ保存するようにしました。

EventBridge

以下のルールをEventBridgeに作成し、IP setへの変更を検知します。
ターゲットにLambdaを指定し、DynamoDBへの登録とSlack通知を行います。

Lambda

CloudTrailからのイベントは以下の形式で通知されます。

注意が必要な点として、addressesにはIP set変更後のすべてのIPアドレスが格納されています。追加/削除されたIPアドレスを取得するために、変更前のIPアドレスをDynamoDBに格納しておき、変更前後のデータ差分から変更されたIPアドレスを取得しています。

DynamoDB

DynamoDBに以下のようなテーブルを作成し、Lambdaで受け取ったイベント内容からレコードを作成します。

キー 説明
ip_cidr string WAFに登録されたCIDR (Primary Key)
action string “block” または “unblock”
actor_name string 作業者名
requested_at string (ISO8601) ブロック/解除を要求した時刻
removed_at string (ISO8601, nullable) 実際に解除された時刻

これらの内容をLambdaからSlackに通知することで、誰が・いつ・どのIPを・ブロック/解除したのかがわかるようになります。

WAFブロックのSlack通知サンプル

また、ブロックした理由などの情報をSlackのスレッドに追記しておけば、時間が経った後でもどういった意図で作業したのかを確認しやすくなります。

IP setにIPアドレスを溜めっぱなしにしていませんか?

ところで、一度ブロックしたIPアドレスをそのままにしていませんか?

IP setに登録できる件数の上限は10,000件です。登録件数が多いことによるパフォーマンスへの影響については公式ドキュメントでは確認できませんでしたが、別のリスクも考えられます。ISP(インターネットサービスプロバイダー)によるIPアドレスの譲渡や再割り当てにより、過去にブロックしたIPアドレスが別のユーザーに割り当てられる可能性がゼロではないためです。ブロックしたまま放置していると、無関係なユーザーのアクセスを誤ってブロックしてしまうかもしれません。

そこで上記の仕組みを拡張し、一定期間が経過したIPアドレスを自動で解除する仕組みも実装しました。

システム構成:自動解除追加バージョン

WAF操作通知・IP自動解除のシステム構成概要図

図の右上の「日次処理(ブロック解除)」が新しく追加した部分です。

IP setへの登録後、一定期間が経過したIPアドレスをIP setから解除するLambdaを作成しました。EventBridgeのスケジュールからこのLambdaを日次起動します。

これまでの観測から、ブロック後3ヶ月ほどで同じIPから攻撃が来ることもあったため、余裕を持たせて自動解除までの日数は180日としました。

DynamoDB

DynamoDBのテーブルは最終的に以下のようになりました。

キー 説明
ip_cidr string WAFに登録されたCIDR (Primary Key)
action string “block” または “unblock”
actor_name string 作業者名
applied_at string (ISO8601) WAFに反映した時刻
expires_at string (ISO8601) 自動解除予定時刻
ipset_id string WAF IP set ID
ipset_name string 対象のIP set名
region string WAFリージョン
requested_at string (ISO8601) ブロック/解除を要求した時刻
removed_at string (ISO8601, nullable) 実際に解除された時刻
source string “cloudtrail” (手動解除)
または
“auto-unblocker”(自動解除Lambda)
ttl number (epoch) DynamoDB TTL(1年後に物理削除)

この仕組みにより、ブロックから180日が経過したIPアドレスは自動的にIP setから解除されます。また、DynamoDBのTTLを1年に設定しているため、操作履歴は1年間保持されたのち自動で削除されます。

これにより、IP setへの登録件数が際限なく増え続けることを防ぎつつ、一定期間の操作履歴はいつでも確認できる状態を維持できます。

まとめ

今回の仕組みを導入したことで、「誰が・いつ・どのIPを・ブロック/解除したか」をSlack通知でリアルタイムに把握できるようになりました。また、DynamoDBに操作履歴が蓄積されるため、過去の操作を遡って確認したい場合にも役立ちます。

「とりあえずブロックして放置」という運用から一歩進んで、IPブロックの管理を仕組みとして整備できたことは、小さいながらも確実な改善だと感じています。

WAFのIP set運用に課題を感じている方の参考になれば幸いです。

新卒・中途エンジニア募集中!

100%自社内開発!学術に特化した自社サービスで設計からリリースまでフルスタックなスキルを身につけませんか?
テレワーク主体ですがコミュニケーションも活発でチームのつながりも大切にしている環境です。

カジュアル面談からお気軽にお越しください!

採用情報はこちら