概要
シングルページアプリケーションのホスティング先として Cloudfront + S3 を選択した場合、WAFでのIP制限に意図しない落とし穴があるので共有
Cloudfrontのカスタムレスポンスによるシングルページアプリケーションの実装
シングルページアプリケーションのルーティングは仮想的なページ遷移なので、例えば /users
などのURLでアクセスされた時、そのURLのhtmlファイルがないため 403 Forbidden
になる
それを回避するため、Cloudfrontのカスタムレスポンス設定で 403 Forbidden
の場合に 200 OK
で /
にリダイレクトさせる設定をしてシングルページアプリケーションを実現できる
IP制限のためにWAFをCloudfrontにアタッチした時の問題
CloudfrontにIP制限をかけたい場合、WAFを利用して制限できる
が、今回のカスタムレスポンス設定により、WAFでブロックされている(ログにもブロックされたと出る)ものの、アプリケーションのhtmlが見れる結果になる
これは、WAFがブロックした後のレスポンスをCloudfrontのカスタムレスポンスが評価され、200 OK
で /
にリダイレクトされたため
解決方法としてWAFのカスタムレスポンスを設定
サポートで定時された対処法としては、Cloudfrontのカスタムレスポンス設定を変更してとのことでしたが、これではシングルページアプリケーションを構築できないことになる
AWSサポートの方に共有されたドキュメントを読んだところ、
AWS WAF ルールを使用してカスタマイズした応答は、CloudFront カスタムエラーページで定義した応答の仕様よりも優先されます。
の記載があり、WAFのブロック時のカスタムレスポンス設定でstauts: 403と適当なbodyを設定したところ、ステータスを403のままそのWAFのカスタムレスポンスが返り、CloudFront 側のカスタムエラーレスポンスを変更せずに想定している挙動になった
Cloudfront+WAFのカスタムレスポンス評価順
CloudfrontとWAF、両方にカスタムレスポンス設定があり、その時々の設定により評価順が異なる
AWSサポートに問い合わせて確認したCloudfront+WAFのカスタムレスポンス評価順が以下
- WAFのブロック時のカスタムレスポンス設定 (Cloudfrontに接続したオリジンを通ることなくWAFのカスタムレスポンスを返す)
- Cloudfrontのカスタムレスポンス設定 (今回の例のようにエラーコードとレスポンスパス設定によってはCloudfrontに接続したオリジンにアクセスされる可能性がある)
- 上記どちらも一致しない場合 WAFのデフォルトメッセージ403 Forbidden
まとめ
- WAFで制限しログでもブロックを確認できても後続の設定(Cloudfrontなど紐づけるリソース)によっては安心はできない
- WAFがCloudfrontより前でブロックしてくれている認識は危ない
その他プロジェクトによっては残る問題
- Cloudfrontは社内限定やIPを制限したサービスにはメリットは薄い
- WAFによるCloudfrontのIP制限はルールによってクリティカル
- CloudfrontとALBに別々のドメインをつける必要がある
- CloudfrontにバックエンドとしてALBを紐づけた場合、APIの403 Forbiddenもカスタムレスポンスに吸われる
- CloudfrontからALBのアクセスはインターネット経由であり、セキュリティグループで制限できない
- 参考 https://dev.classmethod.jp/articles/setalb_access_to_be_allowed_only_from_cloudfront/
- マネージドプレフィックスを利用して、ALBの直接アクセスを禁止、Cloudfrontからのみに制限する
- 上記では別のCloudfrontからALBにアクセスはできるので、カスタムヘッダで制限する
- 上記でもセキュリティ的にはIP制限より弱い