AWS WAF入門 Webアプリケーションを攻撃から守るルール設計と運用ガイド

Cloud Security

「オンプレのWAFアプライアンスはあったけど、AWSに移行してから何をどう設定すればいいのか分からない」という声をよく聞きます。この記事では、AWS WAFの基本構造から実際のルール設計・コスト管理・ログ分析まで、現場のエンジニアがすぐに使える形で解説します。

AWS WAF入門 Webアプリケーションを攻撃から守るルール設計と運用ガイド

1. なぜAWS WAFなのか?(オンプレのWAFとの違い・背景)

オンプレ環境では、WAFといえばF5 BIG-IP ASMやCitrix Web App Firewallといった高価なアプライアンスが主流でした。ハードウェアの調達から設定、署名の更新まで、専任のネットワークチームが管理するのが当たり前でした。

AWS WAFはその概念を大きく変えています。ハードウェアは一切不要で、AWS管理コンソールから数分で設定が完了します。スペックの「盛り過ぎ」も「不足」も起きない従量課金制で、トラフィックが増えても自動的にスケールします。

オンプレWAFとの主な違いをまとめると:

初期投資: オンプレは数百万〜数千万円のアプライアンス費用が発生するのに対し、AWS WAFはWebACL 1つあたり月5USDから
署名更新: AWSマネージドルールは自動更新。オンプレでは手動アップデートが必要で、適用漏れのリスクが常にあった
スケーリング: AWS WAFはトラフィックに応じて自動スケール。オンプレでは最大負荷に合わせた機器選定が必要だった
可視性: CloudWatchやS3へのログ連携が標準機能。オンプレではSIEM連携の構築コストが別途かかっていた

ただし「オンプレの方が細かい制御ができる」という場面もあります。SSL/TLSの復号・再暗号化をWAFで行いたい場合や、独自の脅威インテリジェンスフィードを組み込む場合は、AWS WAFだけでは対応しきれないこともあります。その点は正直に認識しておく必要があります。

2. AWS WAFの基本的な仕組み(WebACL・ルール・ルールグループ)

AWS WAFを理解するには、3つの概念を押さえておけば十分です。

WebACL(Web Access Control List)

WebACLはAWS WAFの最上位の管理単位です。ALB、Amazon CloudFront、Amazon API Gateway、AWS AppSyncなどのリソースにアタッチして、そのリソースへのHTTP/HTTPSリクエストをフィルタリングします。

オンプレのWAFアプライアンスで言えば「仮想サービス(Virtual Server)」に相当します。1つのWebACLに複数のルールを持たせ、リクエストを評価する順序(優先度)を設定します。

ルール(Rule)

個々の検査条件と、その条件に一致したときのアクション(Allow / Block / Count / CAPTCHA / Challenge)の組み合わせです。

条件には以下のような要素を使えます:

IPアドレスセット: 特定のIPやCIDRブロックを許可・拒否
地理的マッチ: 特定の国からのアクセスをブロック
SQLインジェクション検出: クエリパラメータやリクエストボディの検査
XSS検出: クロスサイトスクリプティングのパターンマッチ
レートベース: 5分間のリクエスト数によるDDoS緩和
文字列マッチ: URI、ヘッダー、クッキーの特定文字列を検査
正規表現マッチ: 柔軟なパターンマッチング

各ルールには優先度(Priority)を設定します。数値が小さいほど先に評価されます。オンプレのACLと同じ考え方です。

ルールグループ(Rule Group)

複数のルールをまとめたコレクションです。ルールグループには2種類あります。

AWSマネージドルールグループ: AWSが管理・更新するルールセット。有効化するだけで主要な脅威に対応できる
カスタムルールグループ: 自分で作成・管理するルールセット。特定のアプリケーション要件に合わせて設計できる

AWS WAF入門 Webアプリケーションを攻撃から守るルール設計と運用ガイド - 解説

3. AWSマネージドルールを使った基本設定手順(コンソール操作)

まずはマネージドルールを使った基本設定から始めましょう。カスタムルールは後から追加できます。

WebACLの作成

AWS管理コンソールで「WAF & Shield」サービスを開き、「Web ACLs」→「Create web ACL」の順に進みます。

Name: WebACLの名前(例: production-web-acl)
Resource type: アタッチ先のリソース種別を選択。CloudFrontの場合は「Amazon CloudFront distributions」、それ以外は「Regional resources」
Region: Regional resourcesの場合はリソースと同じリージョンを選択

「Associated AWS resources」で保護対象のALBやAPI GatewayのARNを追加します。後から変更も可能です。

AWSマネージドルールグループの追加

「Add rules」→「Add managed rule groups」を選択し、「AWS managed rule groups」を展開します。代表的なルールグループは以下の通りです。

AWSManagedRulesCommonRuleSet: OWASPのトップ10を含む汎用的なルールセット。まずこれを有効化する
AWSManagedRulesKnownBadInputsRuleSet: Log4Shell(CVE-2021-44228)などの既知の脆弱性悪用パターンをブロック
AWSManagedRulesSQLiRuleSet: SQLインジェクション特化ルール
AWSManagedRulesLinuxRuleSet: Linuxサーバーへの攻撃パターン(LFI等)
AWSManagedRulesBotControlRuleSet: ボットトラフィックの管理(追加料金あり)

重要:最初は「Count」モードで動作確認する

ルールグループを追加するとき、Override rule group action to「Count」を選択することを強く勧めます。CountモードではブロックせずにCloudWatchメトリクスに記録するだけです。本番環境に突然Blockモードで適用すると、正規リクエストが誤検知でブロックされてサービス障害を起こすケースが後を絶ちません。

1〜2週間CountモードでログをチェックしてからBlockモードに切り替えるのが現場での鉄則です。

デフォルトアクションの設定

どのルールにも一致しなかったリクエストに対するデフォルトアクションを「Allow」または「Block」から選択します。一般的なWebアプリケーションでは「Allow」を選択し、ルールでブロックしたいリクエストを明示的に定義するホワイトリスト型ではなく、ブラックリスト型の設計にします。

4. カスタムルールの作り方(SQLインジェクション・XSS・レートリミット)

マネージドルールで対応しきれない要件にはカスタムルールを作成します。AWS CLIを使った操作例も合わせて紹介します。

SQLインジェクション検出ルール

コンソールで「Add rules」→「Add my own rules and rule groups」→「Rule builder」を選択します。

Name: custom-sqli-detection
Type: Regular rule
If a request: matches the statement
Inspect: All query parameters
Match type: Contains SQL injection attacks
Action: Block(Countで確認後に変更)

URLデコード、HTMLエンティティデコードなどのテキスト変換を組み合わせることで、エンコードによる回避を防げます。

XSS検出ルール

SQLインジェクションと同様の手順で、「Match type」に「Contains XSS injection attacks」を選択します。検査対象は「Body」と「All query parameters」の両方を設定するとより効果的です。ただし、リクエストボディの検査にはサイズ制限(デフォルト8KB)があるため、大きなリクエストボディを扱うAPIでは注意が必要です。

レートベースルール(DDoS緩和)

特定のIPアドレスからの過剰なリクエストを制限します。

Name: rate-limit-per-ip
Type: Rate-based rule
Rate limit: 2000(5分間の最大リクエスト数。サイトの正常トラフィックに合わせて調整)
IP address to use for rate limiting: Source IP address
Action: Block

レートベースルールは評価に最低30秒かかることを覚えておいてください。突発的な短時間攻撃には対応が遅れることがあります。より厳格なDDoS対策が必要な場合はAWS Shieldの採用を検討します。

AWS CLIでのルール確認

# WebACLの一覧取得(Regionalリソース) aws wafv2 list-web-acls --scope REGIONAL --region ap-northeast-1 # WebACLの詳細確認 aws wafv2 get-web-acl --name production-web-acl --scope REGIONAL --id --region ap-northeast-1 # CloudFront用はSCOPE=CLOUDFRONT、リージョンはus-east-1固定 aws wafv2 list-web-acls --scope CLOUDFRONT --region us-east-1

5. 料金の仕組みとコスト見積もり

2026年3月時点のAWS WAF料金体系は以下の通りです(東京リージョン)。

課金項目 料金(USD) 備考
WebACL $5.00 / 月 アタッチするリソース数に関わらず1つにつき
ルール $1.00 / 月 カスタムルール1つあたり。マネージドルールグループはグループ単位
マネージドルールグループ(無料) $0 Core Rule Set、Known Bad Inputs等
Bot Control(基本) $10.00 / 月 Bot Controlルールグループの追加料金
リクエスト処理 $0.60 / 100万件 全リクエストを処理した数

月間コスト試算例:

月間1,000万リクエストのWebアプリケーションにWebACL 1つ+カスタムルール3つ+無料マネージドルールグループ2つを設定した場合:

・WebACL: $5.00
・カスタムルール(3つ): $3.00
・マネージドルールグループ(2つ): $0
・リクエスト処理(1,000万件): $6.00
合計: 約$14.00 / 月

オンプレのWAFアプライアンスが年間数百万円かかることを考えると、コスト面での優位性は明らかです。ただし、CloudFrontとALBの両方にWebACLをアタッチした場合はWebACL料金が2倍かかります。二重アタッチは「よくあるトラブル」でも後述しますが、設計段階で整理しておくことが重要です。

6. 応用・実務Tips(ALB/CloudFront/API Gatewayへのアタッチ、ログ分析)

リソース別のアタッチ先とスコープ

ALB(Application Load Balancer): Regional スコープのWebACL。リージョン単位の管理になるため、複数リージョンで運用する場合は各リージョンにWebACLが必要
Amazon CloudFront: CloudFront スコープのWebACL。必ず us-east-1 で作成する必要がある(これが忘れがち)
Amazon API Gateway: Regional スコープのWebACL。ステージ単位でアタッチ可能

ログ分析の設定

AWS WAF Full Logsを有効にすると、すべてのリクエストの詳細ログが記録されます。設定手順は以下の通りです。

1. Amazon Data Firehoseでデリバリーストリームを作成(宛先: S3)
2. ストリーム名は必ず「aws-waf-logs-」で始める(この命名規則は必須)
3. WAF管理コンソールの「Logging and metrics」→「Enable logging」でストリームを指定

S3にログが溜まったらAmazon Athenaで分析できます。Athenaのテーブル定義はAWSが公式DDLを提供しているので、そのまま使えます。

-- Athenaでブロックされたリクエストを集計するクエリ例 SELECT from_unixtime(timestamp/1000) AS request_time, action, httprequest.clientip AS client_ip, httprequest.uri AS uri, terminatingruleid AS matched_rule FROM waf_logs WHERE action = 'BLOCK' AND from_unixtime(timestamp/1000) > current_timestamp - interval '1' day ORDER BY timestamp DESC LIMIT 100;

CloudWatchメトリクスの活用

各ルール・ルールグループごとにCloudWatchメトリクスが自動生成されます。「AllowedRequests」「BlockedRequests」「CountedRequests」を監視することで、異常なトラフィック増加に早期対応できます。CloudWatchアラームを設定して、BlockedRequestsが急増したときにSNS通知を飛ばすのが実用的な監視設計です。

クラウドセキュリティの基礎については、姉妹サイトSecurityMasters.JPでも詳しく解説しています。

7. よくあるトラブルと対処法

トラブル1:正規ユーザーがブロックされる(誤検知)

最も多いトラブルです。例えば、投稿フォームにSQLっぽい文字列(「SELECT」「DROP」等)が含まれるコメントを送信するとブロックされることがあります。

対処法: まずCountモードで運用してログを確認します。誤検知が多いルールは「Rule action override」で特定のルールだけCountに変更できます。AWSManagedRulesCommonRuleSetの特定のルール(例: GenericRFI_QUERYARGUMENTS)だけをCountにする、といった細かい制御が可能です。

トラブル2:ルールの優先順位ミス

「特定のIPを明示的に許可したいのにブロックされる」というケースは、Allowルールよりも優先度の高いBlockルールが先に評価されていることが原因です。

対処法: Allowルールは優先度を低い数値(先に評価される)に設定します。「自社のIPはどんな条件でも許可する」ルールを最上位に置くのが基本です。

トラブル3:CloudFrontとALBへの二重アタッチ

CloudFront→ALBという構成でCloudFrontにもALBにも別々のWebACLをアタッチしているケースがあります。これ自体は可能ですが、リクエストが2回WAFで処理されるためコストが2倍になります。また、CloudFrontでBlockしたリクエストはALBに到達しないため、ALB側のWAFログにはブロック記録が残りません。監視設計が複雑になるため、原則どちらか1箇所にまとめることを推奨します。

トラブル4:CloudFront用WebACLをus-east-1以外で作成してしまう

CloudFrontのWebACLは必ずus-east-1(バージニア北部)で作成しなければなりません。別リージョンで作成したWebACLはCloudFrontにアタッチできません。コンソールでCloudFrontのディストリビューション設定を開いたときに「WAFが見つからない」という状況は大抵これが原因です。

トラブル5:レートベースルールが想定通り動かない

ALBの背後にWebサーバーが複数台ある構成や、CloudFrontを経由している場合、クライアントのIPアドレスではなく中間サーバーのIPが評価されることがあります。

対処法: レートベースルールの「IP address to use」で「IP address in header」を選択し、X-Forwarded-ForヘッダーのIPを参照するよう設定します。

AWS WAF入門 Webアプリケーションを攻撃から守るルール設計と運用ガイド - まとめ

8. まとめテーブル

やりたいこと AWS WAFの機能 オンプレ相当
SQLインジェクション・XSSをブロック AWSManagedRulesCommonRuleSet / カスタムルール WAFシグネチャルール
特定IPをブロック・許可 IPセットルール ACL / 送信元フィルタ
特定の国からのアクセスをブロック 地理的マッチルール GeoIP フィルタ
DDoS・ブルートフォース緩和 レートベースルール コネクション数制限
ボット対策 Bot Control(追加料金) Captcha / チャレンジ設定
全リクエストのログ記録 WAF Full Logs → Firehose → S3 WAFアクセスログ
ログ分析・可視化 Amazon Athena / CloudWatch SIEM連携
脅威対応の自動化 Lambda + WAF API IPS連携 / スクリプト

AWS WAFは「設定すれば終わり」ではなく、定期的なログレビューとルールの見直しが欠かせません。最初はマネージドルールをCountモードで動かし、誤検知がないことを確認してからBlockモードに切り替える。この手順を守るだけで、多くのトラブルを未然に防げます。

オンプレのWAF運用経験があるエンジニアにとって、AWS WAFの概念はそれほど違和感なく受け入れられると思います。「署名更新を手動でやらなくていい」「ハードウェアのキャパシティを気にしなくていい」という解放感を、ぜひ体験してみてください。

AWS WAFの設定、思ったより複雑でしたか?

「Countモードで確認してからBlockに切り替える」のように、実際の現場では教科書に載っていないコツがたくさんあります。
オンプレの経験を活かしながら、現場で使えるクラウドスキルを体系的に身につけたい方へ、メルマガで実践的なクラウド活用ノウハウをお届けしています。

コメント

タイトルとURLをコピーしました