HTTPSリダイレクトの挙動を検証してみた
初めに
表題の通り、GCPのロードバランサーでHTTPとHTTPSの設定をいろいろ試していたら、ブラウザによって挙動が異なることがわかりました。
基本的にはブラウザの自動HTTPS機能の違いなのですが、ところどころ予想外の動作があったので、そちらについても記載をしていきます。
前提
なお、今回はサンドボックスで下記の構成を使っていました。
- Google Cloud Platform
- Cloud Load Balancer
- Terraform
- 静的サイト(Cloud Storage + CDN)
検証内容
本来はHTTPからHTTPSへのリダイレクト設定がスタンダードかと思うのですが、ブラウザの挙動を詳しく調べるため、あえて異なる設定パターンを試してみました。
標準設定: HTTPからHTTPSへのリダイレクト
まず、推奨される標準的な設定を確認します。
# コンテンツ配信用URLマップ
resource "google_compute_url_map" "website_url_map" {
name = "dashboard-url-map"
default_service = google_compute_backend_bucket.website_backend.id
description = "URL map for dashboard static website"
}
# リダイレクト用URLマップ
resource "google_compute_url_map" "https_redirect" {
name = "dashboard-https-redirect"
description = "URL map to redirect HTTP to HTTPS"
default_url_redirect {
redirect_response_code = "MOVED_PERMANENTLY_DEFAULT"
strip_query = false
https_redirect = true
}
}
# HTTPプロキシ(リダイレクト専用)
resource "google_compute_target_http_proxy" "website_http_proxy" {
name = "dashboard-http-proxy"
url_map = google_compute_url_map.https_redirect.id # リダイレクト用
}
# HTTPSプロキシ(コンテンツ配信用)
resource "google_compute_target_https_proxy" "website_https_proxy" {
name = "dashboard-https-proxy"
url_map = google_compute_url_map.website_url_map.id # コンテンツ配信
}
この標準設定では、HTTPアクセスを確実にHTTPSにリダイレクトします。
検証パターン1: HTTPでもコンテンツ配信(本来は非推奨)
ブラウザの挙動を確認するため、あえてHTTPとHTTPSの両方でコンテンツを配信する設定を試しました。
# HTTPプロキシ(コンテンツ配信用 - 検証目的)
resource "google_compute_target_http_proxy" "website_http_proxy" {
name = "dashboard-http-proxy"
url_map = google_compute_url_map.website_url_map.id # 本来は非推奨
}
# HTTPSプロキシ(コンテンツ配信用)
resource "google_compute_target_https_proxy" "website_https_proxy" {
name = "dashboard-https-proxy"
url_map = google_compute_url_map.website_url_map.id # 同じコンテンツ配信
}
この設定では、HTTPでもHTTPSでも同じコンテンツが配信されるはずでした。
結果
# サーバー側の動作確認
curl -I http://35.186.230.40
# → HTTP/1.1 200 OK (正常にコンテンツ配信)
全ブラウザ共通の挙動:
- HTTPでアクセス → 自動的にHTTPSにリダイレクトされた
- ブラウザが勝手にHTTPSに変更してアクセス
検証パターン2: HTTPルールなし(HTTPS専用)
さらに、HTTPS専用の設定も試しました。HTTPのフォワーディングルールを削除する設定です。
# HTTPプロキシとフォワーディングルールを削除
# ポート80でのアクセス受付なし
結果
# サーバー側の動作確認
curl http://35.186.230.40
# → curl: (7) Failed to connect (接続拒否)
ブラウザごとの挙動の違い:
- Google Chrome: HTTPでアクセス → HTTPSにリダイレクト成功
- Safari・Edge: HTTPでアクセス → エラー画面
原因
パターン1での全ブラウザHTTPS動作
現代のブラウザには積極的なセキュリティ機能があるようでした:
- Chrome: 自動HTTPSアップグレード機能
- Safari: 最近のバージョンでHTTPS優先機能が強化
- Edge: Chromeと同様の機能
つまり、サーバー側でHTTPコンテンツを配信していても、全ブラウザが勝手にHTTPSに変更してアクセスされるようになるということのようです。
パターン2でのブラウザ間の違い
HTTPエンドポイント(ポート80)が存在しない場合:
Chrome:
- HTTPでアクセスしようとする
- 「あ、接続できないからHTTPSにしてみよう」と自動判断
- 勝手にHTTPSに変更してアクセス
- ✅ 成功
Safari・Edge:
- HTTPでアクセスしようとする
- サーバーから応答なし(ポート80が閉じている)
- ❌ エラー表示
最終的な設定
# リダイレクト用URLマップ(標準設定)
resource "google_compute_url_map" "https_redirect" {
name = "dashboard-https-redirect"
description = "URL map to redirect HTTP to HTTPS"
default_url_redirect {
redirect_response_code = "MOVED_PERMANENTLY_DEFAULT"
strip_query = false
https_redirect = true
}
}
# HTTPプロキシ(リダイレクト専用)
resource "google_compute_target_http_proxy" "website_http_proxy" {
name = "dashboard-http-proxy"
url_map = google_compute_url_map.https_redirect.id # リダイレクト用
}
構成図
HTTP (Port 80) → HTTP Proxy → Redirect URL Map → 301 Redirect → HTTPS
HTTPS (Port 443) → HTTPS Proxy → Content URL Map → Backend Bucket → Content
動作確認
上記の設定を適用後、下記を実行して動作を確認します。
cd apps/terraform/gcp/environments/dev/dashboard
# 変更内容を確認
terraform plan
# 標準的なリダイレクト設定を適用
terraform apply
結果
# HTTPアクセス(301リダイレクトを確認)
curl -I http://35.186.230.40
# → HTTP/1.1 301 Moved Permanently
# → Location: https://35.186.230.40/
# HTTPSアクセス(コンテンツ配信を確認)
curl -I https://dev.dashboard.my-learn-iac-sample.site
# → HTTP/2 200
# 注意:IPアドレス直接のHTTPSアクセスは証明書エラーが発生
# curl -I https://35.186.230.40
# → curl: (35) LibreSSL SSL_connect: SSL_ERROR_SYSCALL
# 理由:SSL証明書はドメイン名用に発行されているため
すべてのブラウザでHTTPアクセスが正常にHTTPSにリダイレクトされることを確認できました。
学んだこと
ブラウザの自動HTTPS機能について
- 全ブラウザ: HTTPコンテンツが配信できる環境では自動的にHTTPS化
- Chrome: HTTPエンドポイントがなくても勝手にHTTPS化を試行
- Safari・Edge: HTTPエンドポイントがないと素直にエラー表示
設計の考慮点
- ブラウザの自動HTTPS機能に頼りすぎない
SSL/TLS証明書とアクセス方法について
今回の検証で、HTTPSアクセスの際の注意点も明確になりました:
- HTTPアクセス: IPアドレス直接でも問題なく動作(証明書不要)
- HTTPSアクセス: ドメイン名でのアクセスが必要(証明書がドメイン名用に発行されているため)
- 本番環境: ユーザーはドメイン名でアクセスするため、この動作は自然
最後に
ここまでお読みいただきありがとうございました。
基本的にはブラウザの自動HTTPS機能による挙動でしたが、細かいパターンによって予想外の動作があったので勉強になりました。
今回の主な学び
- 標準的なHTTPSリダイレクト設定の重要性を再確認した
- ブラウザの自動HTTPS機能の違いを実際に確認できた
- 検証目的での設定変更から得られる知見の価値を理解した
- 全ブラウザで統一した動作を保証する設計の重要性を実感した
Discussion