タイトルの通りですが、意外とハマったのでメモです.
やりたいこと
- http(80)できたらhttps(443)でリダイレクトさせたい
原因となった箇所
筆者の場合原因は
- ロードバランサーの設定.
- .htaccessの設定
の二箇所.
- ロードバランサーのポートの設定(わかる方はここ見た瞬間にお察しかと思います笑)
- 80->80
- 443->80
失敗例
今回CakePHPだったのでwebroot内の.htaccessに↓のように記述しました.
.htaccess
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/sample/$1 [R=301,L]
これにhttpで指定のurlにアクセスすると想定通りにはいかず, ブラウザから「リダイレクトループ含まれてるよおおおおおお」って怒られる.
原因
- 上記ロードバランサーのポート設定で443が80に書き換わってしまうわけです.
つまり
- http(80)でアクセスします.
- ELBが80をEC2に80で渡して
- EC2の.htaccessが「80を443でリダイレクトするぞ!」ってなる
- ブラウザは443でアクセス
- ELBは設定を守って「443を80で流すぞ!」となって443をEC2に80で渡す
すると3に戻るわけですね.
あとは3~5を無限ループ.
解決
.htaccess を↓のようにしましょう.
htaccess
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !=https // ここでリダイレクト指定
RewriteRule ^(.*)$ https://%{HTTP_HOST}/sample/$1 [R=301,L]
ELBのようなリバースプロキシで https してるときは X-Forwarded-Proto ヘッダを見るようですね.
ちなみに %{HTTPS} は mod_ssl の判定で使うようです.
こうするとELBへの接続プロトコルを判別して「httpsじゃない場合はhttpsでリダイレクトしてこいよ」という意図した実装になるわけですね.
すごく簡単なことかも知れないですが, ELBの存在をうっかり忘れるとしばらくはまる可能性があるのでお気をつけください.