🌈

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機能による挙動でしたが、細かいパターンによって予想外の動作があったので勉強になりました。

今回の主な学び

  1. 標準的なHTTPSリダイレクト設定の重要性を再確認した
  2. ブラウザの自動HTTPS機能の違いを実際に確認できた
  3. 検証目的での設定変更から得られる知見の価値を理解した
  4. 全ブラウザで統一した動作を保証する設計の重要性を実感した

Discussion