原因と解決策
発生している問題:
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
を考慮せずにリダイレクトを設定し、問題が起きることを確認します。
- Apacheにリダイレクトを設定
以下のリダイレクトルールをApacheの設定ファイルに記述RewriteEngine On RewriteRule ^/?from$ /to [R=301,L]
この時点では、ApacheはALBからの
http
通信しか認識していないため、このルールはhttp
でのリダイレクトを生成します。 -
動作確認
curl
コマンドでhttpsのURLにアクセスします。curl -I https://example.com/from
【確認する結果】
Location
ヘッダーが意図せず`http://`になっていることを確認します。
X-Forwarded-Proto を参照する設定
次に、X-Forwarded-Proto
ヘッダーをチェックする条件を追記して、問題を解決します。
- Apacheの設定ファイルを編集
先ほどの設定に、を以下の通りに修正します。RewriteRule ^/?from$ %{HTTP:X-Forwarded-Proto}://%{HTTP_HOST}/to [R=301,L]
【ポイント】
%{HTTP:X-Forwarded-Proto}
にはリクエスト時のプロトコル(httpかhttpd)が格納されているため、それに合わせてリダイレクト先URLを生成できます。 -
動作確認
再度、同じcurl
コマンドを実行します。curl -v https://example.com/from
【確認する結果】
Location
ヘッダーが正しく`https://`になっていることを確認します。
httpsにリダイレクトされていることが確認できます!
まとめ
絶対パスで指定するのがいいと思いました。
RewriteRule ^/?from$ https://example.com/to [R=301,L]