iCLUSTAで運用しているサイトを常時SSL化しようと、.htaccessにhttpsリダイレクトを書いた。なのに、いくらアクセスしてもhttpのまま。転送されない――。もし今そんな状況で頭を抱えているなら、原因はあなたの記述ミスではなくiCLUSTA側の仕様である可能性が高いです。
私はGMOのサーバーには何度もひどい目にあってきたので、新規では絶対に契約しないことにしています。…が、残念ながら過去に契約したまま使っているサイトがいくつか残っていて、その一つをSSL化したときにまさにこの現象に遭遇しました。またかGMO、と。
ということで、iCLUSTAで.htaccessのhttpsリダイレクトを効かせる正しい記述方法を、なぜ普通の書き方だと動かないのかという理由もあわせて紹介します。
関連記事:ブログのレンタルサーバーを移転しました。ホスティングの評判はきちんと調べるべきと実感!
一般的な書き方はiCLUSTAでは効かない
.htaccessでサイト全体をhttpsへリダイレクトする場合、多くの解説記事では以下のように書かれています。私も最初はこれを置きました。
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
「httpsがオフのときだけhttpsへ飛ばす」という、ごく素直な記述です。ほとんどのレンタルサーバーではこれで問題なく動きます。ところがiCLUSTAに置くと、まったく機能しない。
GMOのレンタルサーバーに長年苦しめられてきた私は、ここですぐにピンときましたw「これは記述が間違っているのではなく、サーバーの仕様だ」と。
なぜ %{HTTPS} off では判定できないのか
調べてみたところ、やはりビンゴでした。iCLUSTAでは %{HTTPS} による判定がそもそも当てにならないのです。
仕組みとしてはこうです。iCLUSTAのようにロードバランサーやプロキシの手前でSSL通信を終端している構成では、暗号化の処理はプロキシ側で済まされ、その先のWebサーバー(Apache)へは平文のhttpとして中継されます。つまりApacheから見た %{HTTPS} は、ブラウザがhttpsで来ていても常に off のまま。だから「offならリダイレクト」という条件が延々と成立し続けたり、逆に判定が噛み合わず転送されなかったりするわけです。
GMOの公式ヘルプにも、この %{HTTPS} を使った記述は非対応だと明記されていました。
利用可能ディレクティブに関して
以下の記述はiCLUSTAサーバーにて非対応となっております。
下記の記載があった場合にはリダイレクトが有効になりませんのでご注意ください。RewriteCond %{HTTPS} off
はいはい、GMOGMO。公式が非対応と言っているのですから、こちらの書き方をいくら見直しても無駄だったわけです。
iCLUSTAで動く.htaccessの書き方
では何で判定すればいいのか。答えは、サーバー変数 %{HTTPS} ではなく環境変数 %{ENV:HTTPS} を見ることです。プロキシで終端された構成でも、こちらには実際のプロトコルの状態が渡ってきます。
私の環境では、以下のように書き換えたところ無事にhttpsへ転送されるようになりました。
RewriteEngine on
RewriteCond %{ENV:HTTPS} !^on$
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
%{ENV:HTTPS} !^on$ は「環境変数HTTPSの値がonでないとき」という条件です。つまりhttpsで接続できていないアクセスだけをhttpsへ301リダイレクトする、という意味になります。やりたいことは最初の記述とまったく同じで、判定に使う変数を差し替えただけです。
なお、プロキシ経由の構成では %{HTTP:X-Forwarded-Proto} というリクエストヘッダで元のプロトコルを判定する手もあり、他社のサーバーではこちらが定番になっていることもあります。ただしヘッダが渡ってくるかは環境しだいなので、iCLUSTAではまず上の %{ENV:HTTPS} を使う書き方を試すのが確実です。
同じ書き方でどのサーバーでも通ると思い込んでいると、こういう固有仕様にハマって時間を溶かします。iCLUSTAで.htaccessのリダイレクトが効かないときは、まず %{HTTPS} を %{ENV:HTTPS} に置き換えて試してみてください。