AWS WAF × ALB:その「壁」は本当に機能しているか?現場で語るトラフィック検査の深淵
こんにちは、SREチームのリードエンジニアです。
皆さんのシステムにおいて、ALB(Application Load Balancer)のフロントにAWS WAFを配置するのは今や「作法」です。しかし、実際に「どのタイミングで」「何が検査され」「どう弾かれるのか」を正確に理解して運用している人は、意外と少ないものです。
今回は、ALBにおけるWAFのインスペクションポイントと、現場で遭遇しやすい「詰まりどころ」を、パケットの旅路を追うように解説します。
—
1. WAFはどこで通信を検査しているのか?
まず、勘違いしがちなのが「WAFが通信のどこに割って入るのか」という点です。WAFはALBという「L7ロードバランサー」のコンテキスト上で動作します。
トラフィックは、以下の順序で処理されます。
1. Client からの HTTP/HTTPS リクエストが ALB のリスナーに到達。
2. ALB がパケットを受け取り、TCPコネクションを終端(TLSオフロード)。
3. AWS WAF がALBの内部エンジンと密結合し、HTTPリクエストヘッダーおよびボディ(制限あり)を検査。
4. WAF が許可(Allow)と判断した場合のみ、ALBがバックエンド(Target Group)へリクエストを転送。
ここで重要なのは、「WAFの判定はALBがバックエンドにリクエストを投げる直前に行われる」ということです。つまり、WAFでブロックされたリクエストは、バックエンドのコンテナやEC2には1バイトも届きません。これが「エッジ保護」の最大のメリットであり、バックエンドのリソース保護にも直結します。
—
2. 検査のプロセスと「レートリミッティング」の魔力
WAFが提供する機能の中で、最も実務で効くのが「レートリミッティング(レートベースのルール)」です。
なぜレートリミッティングが重要か?
特定のIPアドレスから短時間に過剰なリクエストが送られると、ALBの接続数制限を圧迫し、結果として他の健全なユーザーまで巻き添えを食らいます。これを防ぐために、WAF側で「5分間に1000リクエスト以上なら一時ブロック」といった制限をかけます。
Pythonによる検証用コード
実際にレートリミットが効いているか確認する際、私たちはよく以下のような簡易スクリプトを回して挙動を見ます。
import requests
import time
# 検証用ターゲットURL
url = "https://api.example.com/v1/resource"
# 短時間で100回叩く(レート制限にかかるか確認)
for i in range(100):
try:
response = requests.get(url)
print(f"Request {i+1}: Status {response.status_code}")
# 制限を回避したい場合はここに sleep を入れるが、
# 今回はあえて連打してWAFの挙動を確認する
except Exception as e:
print(f"Error: {e}")
もしWAFの設定が正しければ、一定回数を超えた瞬間に 403 Forbidden が返されるはずです。このとき、ALBのアクセスログには、WAFがブロックしたことを示す waf というフラグが記録されます。
—
3. SQLi / XSS 防御の実務:マネージドルールの活用
「SQLインジェクション(SQLi)」や「クロスサイトスクリプティング(XSS)」のシグネチャを自前でメンテナンスするのは、現代のインフラエンジニアにとって非現実的です。AWSが提供する「マネージドルール」を活用しましょう。
設定の勘所
マネージドルールを適用する際、以下の Scope を意識することが肝要です。
AWSManagedRulesCommonRuleSet: 基本的なWeb攻撃を防御。まずはこれ。AWSManagedRulesSQLiRuleSet: SQLi特有のパターンを検査。AWSManagedRulesAmazonIpReputationList: 悪意あるボットのIPリスト。
特にSQLiルールを適用する場合、Body の検査サイズ上限(デフォルト8KB)に注意してください。大きなJSONペイロードをPOSTするAPIの場合、ボディの先頭しか検査されず、後半に隠された攻撃コードを検知できないケースがあります。
—
4. 現場で役立つデバッグ手順
WAFで「正常な通信までブロックされた」という悲鳴が上がったとき、どう切り分けるか。以下の手順を推奨します。
1. WAFの「サンプリング」機能を活用する
WAFコンソールの「サンプリングされたリクエスト」を確認してください。どのルールIDがどのリクエストを弾いたのか、一発で分かります。
2. X-Amzn-Trace-Id ヘッダーを追う
ALBが付与するこのヘッダーをバックエンドのログにも残しておきましょう。WAFでブロックされたリクエストと、バックエンドに到達したリクエストの紐付けが容易になります。
3. ルールを「カウントモード」で動かす
いきなりブロック(Block)にせず、まずは「カウント(Count)」モードで適用し、CloudWatchメトリクスでどれくらいのリクエストがマッチするかを数日間監視してください。
# curlでWAFの挙動を確かめる際のTips
# -Iでヘッダーのみ取得し、レスポンスコードを確認する
curl -I -H "User-Agent: <script>alert('xss')</script>" https://api.example.com/
上記のコマンドを叩いて 403 が返ってくれば、あなたのWAFは正しくXSS攻撃を防いでいます。
—
まとめ:防御は「多層」で考える
ALBとWAFの連携は、クラウドネイティブな防御の第一歩です。しかし、WAFは万能ではありません。
- WAFは「既知の攻撃」を防ぐためのフィルター。
- 「アプリケーションのロジック不備」は防げない。
- バックエンド側でもバリデーションを徹底すること。
「WAFがあるから安心」ではなく、「WAFが一番外側の盾であり、内側にはまだ強固な防御がある」という多層防御の意識こそが、障害に強いインフラを作る鍵です。
皆さんのシステムが、今日も安全にリクエストを捌ききっていることを願っています。それでは、また次回の記事で。
コメント