CloudFront + S3で静的サイトを配信していたところ、通信中に接続がリセットされるという現象が頻発した。
ブラウザ上では、HTTPステータスコードが返るのではなく、単純に「接続がリセットされました」と表示される状態だった。
また、サイト自体にはアクセスできるにもかかわらず、Google Search Consoleから sitemap.xml を読み込めない問題も発生していた。
構成
構成は以下の通り。
- Amazon S3
- Amazon CloudFront
- Amazon Route 53
- 独自ドメイン
CloudFrontではIPv6を有効にし、Route 53にはAレコードとAAAAレコードのAliasを登録していた。
症状
主な症状は以下。
- Webサイト閲覧中に接続がリセットされる
- 接続できる場合とできない場合がある
- Google Search Consoleからサイトマップを取得できない
- DNSのAAAAレコードで返されるIPv6アドレスの組み合わせが一定しない
CloudFrontでは接続元などに応じて複数のエッジIPが返されるため、AAAAレコードの回答が毎回異なること自体は異常でないと判断。
問題は、IPv6経由の通信がかなり不安定だったことだった。
原因の切り分け
Windows環境で、IPv4とIPv6を明示して curl を実行した。
curl.exe -4 -I https://cress.cc/
curl.exe -6 -I https://cress.cc/
IPv4を指定した場合は正常に応答する一方、IPv6を指定した場合は接続リセットが頻発した。
この結果から、S3オリジンやCloudFrontのキャッシュ設定ではなく、クライアントからCloudFrontまでのIPv6経路に問題があると判断した。
HTTPの403、502、503、504などが返るのではなく、通信自体が途中でリセットされていたことも、オリジン側ではなく通信経路側の問題と考える材料になった。
対応内容
以下の対応を行った。
1. CloudFrontのIPv6を無効化
CloudFrontの対象ディストリビューションを開き、IPv6を無効にした。
設定変更後、CloudFrontのデプロイが完了するまで待つ。
2. Route 53のAAAAレコードを削除
CloudFrontでIPv6を無効にした後、Route 53に登録していたAAAAレコードのAliasを削除した。
AレコードのAliasはそのまま残した。
これにより、独自ドメインへのアクセスをIPv4に限定した。
結果
IPv6を無効にしてAAAAレコードを削除したところ、接続リセットは発生しなくなった。
Google Search Consoleから取得できなかったサイトマップについても、IPv6経由でCloudFrontへの接続に失敗していた可能性が高い。
補足
CloudFrontでIPv6を無効にした直後は、設定が各エッジへ反映されるまで多少時間がかかる。
また、端末やルーター、DNSリゾルバにAAAAレコードがキャッシュされている場合がある。
Windowsでは、必要に応じて以下を実行する。
ipconfig /flushdns
ブラウザも完全に終了してから再起動する。
まとめ
CloudFront + S3で以下のような症状が出た場合、IPv6経路を疑う価値がある。
- 通信途中で接続がリセットされる
- HTTPエラーコードが返らない
- 接続できたりできなかったりする
- Search Consoleなど外部サービスからの取得も不安定
- IPv4では安定するがIPv6では失敗する
切り分けには、次の2コマンドが有効だった。
curl.exe -4 -I https://example.com/
curl.exe -6 -I https://example.com/
IPv6側だけ失敗する場合は、CloudFrontのIPv6を無効化し、Route 53のAAAAレコードを削除することで改善する可能性がある。