原因と解決策

発生している問題:
ALB (Application Load Balancer) でSSL終端を行う構成で、バックエンドのアプリケーションが出力するリダイレクトURLが、意図しない`http://` スキーマになってしまう。

原因:
バックエンドアプリケーションは、ALBからリクエストを受け取るため、自身へのアクセスがhttp通信であると認識している。そのため、相対パスで設定されたリダイレクトルールからリダイレクト先URLを生成する際に `http://` でURLを生成してしまう。

解決策:
ALBがクライアントの元のプロトコル情報(https)を格納してバックエンドに渡すX-Forwarded-Protoヘッダーの値を、バックエンド側が参照・信頼するように設定し、正しいプロトコルでURLを生成させる。

以下の状況で困っていました。

① httpsでリダイレクト元URLにアクセス

② ALBでhttpに変換され、サーバーへ送信される

③ httpでリダイレクト先URLを生成し、レスポンスを返す

  • リダイレクトルールが相対パスで設定されているからリクエストからリダイレクト先URLを生成しようとする
  • ALBからのリクエストがhttpだから、httpでリダイレクト先URLを生成してしまう

④httpでリクエストがやり直される(危ない)

X-Forwarded-Proto ?

HTTPリクエストヘッダーの一つです。
Webサーバーの手前にリバースプロキシやロードバランサーがある環境で、クライアントがどのプロトコル(HTTPまたはHTTPS)を使って接続してきたかをWebサーバーに伝える役割があります。
値は、httpかhttpsが格納されます。
ALBの場合デフォルトで設定されています。

検証してみる

問題の再現

まず、X-Forwarded-Protoを考慮せずにリダイレクトを設定し、問題が起きることを確認します。

  1. Apacheにリダイレクトを設定
    以下のリダイレクトルールをApacheの設定ファイルに記述
    RewriteEngine On
    RewriteRule ^/?from$ /to [R=301,L]
    

    この時点では、ApacheはALBからのhttp通信しか認識していないため、このルールはhttpでのリダイレクトを生成します。

  2. 動作確認
    curlコマンドでhttpsのURLにアクセスします。

    curl -I https://example.com/from
    

    【確認する結果】
    Locationヘッダーが意図せず`http://`になっていることを確認します。

X-Forwarded-Proto を参照する設定

次に、X-Forwarded-Protoヘッダーをチェックする条件を追記して、問題を解決します。

  1. Apacheの設定ファイルを編集
    先ほどの設定に、を以下の通りに修正します。
    RewriteRule ^/?from$ %{HTTP:X-Forwarded-Proto}://%{HTTP_HOST}/to [R=301,L]
    

    【ポイント】
    %{HTTP:X-Forwarded-Proto}にはリクエスト時のプロトコル(httpかhttpd)が格納されているため、それに合わせてリダイレクト先URLを生成できます。

  2. 動作確認
    再度、同じcurlコマンドを実行します。

    curl -v https://example.com/from
    

    【確認する結果】
    Locationヘッダーが正しく`https://`になっていることを確認します。

    httpsにリダイレクトされていることが確認できます!

まとめ

絶対パスで指定するのがいいと思いました。

RewriteRule ^/?from$ https://example.com/to [R=301,L]