revision: observe / WAF_REACTION: observe
AWS WAF のルールを Block / Count で切り替えて試し、その結果をログ・メトリクス・トレースで確認するための検証環境です。
ブラウザ / テストスクリプト │ ▼ CloudFront + AWS WAF ──ログ──▶ CloudWatch Logs (us-east-1) │ 最後のルールで判定結果 (リクエスト ID・ラベル) を x-amzn-waf-* ヘッダーで渡す ▼ Lambda Web Function (このページ) ──ログ / トレース──▶ CloudWatch Logs / X-Ray (ap-northeast-1) ▼ DynamoDB (ダミーデータ)
Web Function へは CloudFront 経由でしか到達できません (直接アクセスは 403)。
ボタンを押すと、このページから各ルールの「的」になるリクエストを送り、結果を下の表に追加します。
| 時刻 | テスト | ステータス (件数) | 判定 | WAF リクエスト ID | トレース ID |
|---|
| ルール | 対象 | 今の設定 | 止めたときの応答 | 試し方 |
|---|---|---|---|---|
Custom-IPAddresses-Blacklist |
拒否リスト (IP セット) に入れた送信元 | Block | 403 (JSON) | terraform.tfvars の blocked_ip_addresses に自分の IP を入れて apply する |
AWS-AWSManagedRulesAmazonIpReputationList |
AWS が悪性と判断している IP | Block | 403 (WAF 標準) | 自分からは再現できない (外部からのアクセスで記録される) |
Custom-RateLimit-DDoSList |
DDoS リストに載っている IP が 60 秒で 50 件を超えた | Block | 429 (JSON) | 自分からは再現できない |
Custom-RateLimit-Global |
1 IP が 60 秒で 300 件を超えた | Block | 429 (JSON) | 「連続送信」ボタンを数回押す |
Custom-RateLimit-Login |
POST /api/login が 1 IP・60 秒で 10 件を超えた | Block | 429 (JSON) | 「ログインを 20 回送信」ボタン |
Custom-LoginPage-Captcha |
GET /login (ログイン画面) | CAPTCHA | 405 + CAPTCHA 画面 | /login を開く (解答後 300 秒は再表示されない) |
AWS-AWSManagedRulesCommonRuleSet |
XSS・パストラバーサル・User-Agent なし など (/static/ は対象外) | Block | 403 (WAF 標準) | 「XSS」「パストラバーサル」ボタン |
Custom-SizeRestrictionsBody-Exception |
/api/echo 以外への 8KB を超える本文 (ラベルを使った例外ルール) | Block | 413 (JSON) | 「大きな本文」ボタン 2 つ (/api/echo は通り、/api/login は止まる) |
AWS-AWSManagedRulesKnownBadInputsRuleSet |
Log4j (JNDI)・Java の逆シリアル化 など | Block | 403 (WAF 標準) | 「Log4j」ボタン |
AWS-AWSManagedRulesSQLiRuleSet |
クエリ・本文・Cookie・パスの SQL インジェクション | Block | 403 (WAF 標準) | 「SQL インジェクション」ボタン |
Custom-AdminIPAddresses-Whitelist |
許可リスト外の IP からの /admin | Block | 403 (JSON) | 「管理画面」ボタン (許可リストが空なら常に止まる) |
CommonRuleSet の SizeRestrictions_BODY は個別に Count へ上書きしています。最後のルール
Custom-ForwardWafContext は判定結果をこのアプリへ渡すためのもので、常に Count です。
| ステータス | 意味 |
|---|---|
| 200 | WAF を通過した。/api/echo の応答の waf.matchedRules に Count で一致したルールが入る |
| 403 | WAF が Block (本文が JSON なら自作ルール、HTML ならマネージドルール)。アプリの WAF_REACTION=deny でも 403 (error = denied_by_application) |
| 405 | WAF の CAPTCHA (x-amzn-waf-action: captcha)。ブラウザで開くと CAPTCHA 画面が出る |
| 413 | 例外ルール (Custom-SizeRestrictionsBody-Exception) による Block |
| 429 | 回数制限による Block。止まった状態は 1〜2 分ほど続く |
| 応答ヘッダー | 意味 |
|---|---|
x-waf-request-id | WAF のリクエスト ID。WAF ログの httpRequest.requestId、CloudFront ログの x-edge-request-id、アプリログの message.wafRequestId と同じ値 |
x-trace-id | X-Ray のトレース ID (Transaction Search で検索する) |
x-waf-matched-rules | Count で一致したルール (検証用) |
x-waf-reaction | アプリの反応モード (observe / warn / deny) |
waf-serverless-dev/
infra/envs/dev/terraform.tfvars を編集する
rule_actions: ルールごとに block / count (login_captcha は captcha / challenge も可)blocked_ip_addresses / admin_allowed_ip_addresses: IPv4 / IPv6 の CIDRrevisions: WAF_REACTION (observe / warn / deny) の違うリビジョンを 2 つまで配分できるmake plan → make apply (WAF の変更は反映まで数秒〜数分)make waf-test で攻撃テストを流すCount にしたルールに一致したリクエストだけがこのアプリまで届き、WAF_REACTION の反応を確認できます。
waf.clientIp で確認できます)。