背景
S3 → CloudFront → WAFという構成でIP制限付きの静的サイト配信を組みました。構成自体はシンプルですが、実際にやってみるとUIの変更・IPv6の挙動・OACの仕組みなど、いくつも壁にぶつかったので記録します。
[インターネット]
↓
[WAF] ← IP制限
↓
[CloudFront] ← CDN配信 + OAC
↓
[S3バケット] ← HTMLファイル
1. CloudFront作成時の「Enable security」が自動でWeb ACLを付ける
CloudFrontディストリビューション作成時の「Enable security」ステップで何かを選択すると、セキュリティプランが自動的に有効化されます。このプランがあると、後から自分で作ったWeb ACLに付け替えられません。
Failed to associate web ACL with CloudFront distribution:
You can't remove or replace the web ACL for your distribution.
対処法: 「Enable security」では何も選択せずに次に進み、後から自分で作成したWeb ACLを手動で紐付けるか、自動作成されたCreatedByCloudFront-xxxxxを編集してルールを追加する。
2. IPv4のIP Setだけ作ると、IPv6優先で弾かれる
自宅のIPv4アドレスでIP Setを作ってWAFルールを設定したのに、自宅PCからアクセスできない現象が起きました。原因はCloudFrontがデフォルトでIPv6を有効にしており、IPv6対応の回線だとそちらが優先されるためです。WAFログを見ると2404:7a81:...のようなIPv6アドレスでアクセスしていました。
対処法1: IPv6用のIP Setも別途作成する(末尾は/32ではなく/128)。
対処法2: CloudFront側でIPv6を無効化する(ディストリビューション → General → Edit → IPv6のチェックを外す)。
実際に接続してきているIPを特定するには、Web ACLのデフォルトアクションを一時的に「Allow」に変更し、WAFの「Sampled requests」タブでSource IPを確認するのが確実です。
3. S3更新がCloudFrontに反映されない
S3上のファイルを更新してもCloudFront経由では古いまま、というのはキャッシュのしわざです。ブラウザのキャッシュクリアでは解決しません。
対処法: Invalidationを作成する。
CloudFront → ディストリビューション → Invalidations タブ → Create invalidation
Object paths: /index.html (または全体なら /*)
ステータスが「Completed」になるまで1〜3分待ってからハードリロード(Ctrl+F5)します。
4. WAFのルール優先度の考え方
「特定IPのみ許可」は、Allowルールとデフォルトアクションの組み合わせで実現します。
- ルール: 指定したIP Setからのリクエストは
Allow - デフォルトアクション:
Block
この順番を間違える(デフォルトをAllowのままにするなど)と、意図せず全体公開のままになるので注意です。
5. 自分の実IPが確認くんサイトと違うことがある
プロバイダのNATやVPN、IPv4/IPv6混在などの理由で、「確認くん」的なIP確認サイトで見えるIPと、CloudFrontが実際に受け取るIPが一致しないケースがありました。
対処法: Web ACLのデフォルトアクションを一時的に「Allow」にしてアクセスし、WAFの「Sampled requests」でSource IPを直接確認する。理論値より実測値を信じる、という基本に立ち返る場面でした。
まとめ
OAC・WAFルール優先度・IPv4/IPv6の共存・CloudFrontキャッシュの4つが、この構成でつまずきやすいポイントでした。手順の全文(S3バケットポリシー・WAF設定画面の詳細操作含む)はこちらにまとめています。