CDNサービスであるCloudFlareには有償プランがあって、その機能の一つにFlexible SSLというのがあります。
これは図の通り、自分のWebサーバにSSLが入っていなくても、httpsのアクセスに限りCloudFlare側が勝手に証明書を提供してくれるというものです。
SSL利用の本来の目的はユーザーから提供される情報の送信を保護することなので、全部SSLで保護しないと意味ないような気もしますが、とにかくブラウザ上はあの緑の鍵(iPhoneだとグレーの鍵)マークが出せるわけですね。
で、このFlexible SSLなのですが、これを利用するとWordPressのある機能が動かなくなります。それはSSL通信が行われているか否かを判定する is_ssl
という関数です。
この関数は$_SERVER
変数を見てSSLか否かを判定しているんですが、Flexible SSLを利用している場合、CloudFlareからは通常のポート80でリクエストが飛んでくるので、常にfalseとなります。
この結果、SSLを必須とするようなプラグインや管理画面をSSLに制限する機能を使っていたりすると、リダイレクトループが発生します。
- CloudFlare経由でhttps://takahashifumiki.com/login/ にアクセス
- is_sslは常にfalseなので、プラグインが勘違いしてhttps://takahashifumiki.com/login/ にリダイレクト
- 無限ループ
このような仕様であるからこそ、さくらのレンタルサーバーみたいなしょぼいプランでも独自SSLが使えたりするわけなんですが。
対処法
ではどうすればいいかというと、CloudFlareはFlexible SSLの場合、HTTP_X_FORWARDED_PROTO
というヘッダーを送ってきます。このヘッダーがhttpsとなっている場合はSSL通信ということになるので、wp-config.phpに判定式を書き、SSLかどうかを設定してあげます。
// CloudFlareのSSL対応 if( isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && 'https' == $_SERVER['HTTP_X_FORWARDED_PROTO'] ){ $_SERVER['HTTPS'] = 1; $_SERVER['SERVER_PORT'] = 443; }
こういったグローバル変数を書き換える処理はあまり好ましくないのですが、取り急ぎこれで is_ssl は正しく動くようになります。
ポイントはSSLであろうがなかろうがポート80で飛んで来て一つのバーチャルホストで処理するということですね。
以前は違う仕様だったような気もするのですが……ログインできなくなっててビックリしました。
CloudFlareのProプランは月20ドル、1サイト追加ごとに月5ドルと考えると、コスト的には微妙ですが、証明書ってわりと切れちゃったりするのでためしにどうぞ。
ちなみに、WordPress以外でも同様の問題は起こりえるので、Nginxでゴチャゴチャしたりした方が楽かもしれません。