さくらレンタルサーバーのSSL/STL化についてのエトセトラ

さくらレンタルサーバーにて、Wordpressで運用されているサイトのSSL/STL化についての雑感です。

もしこれについてお困りでこのページにたどり着いてしまった方は、この記事は役に立ちません。他サイトの即効性のある記事をご参照ください。(問題が解決した後には読んでほしいかも。)

お品書きは、wp-config.phpに書くパッチについて、リダイレクトループのときのデバッグ方法、さくらさんの気持ち、の三品です。

(2017年6月19日:さくらレンタルサーバーWordpress SSL/TSL対応パッチv.2.0を追記しました。それのみ参照される方は3.1節にお進みください。)

はじめに

ChromeやFirefoxが、パスワードのフォームがあるのにSSL/TLSにしていないと警告が出るようになったということで、さくらレンタルサーバーをご利用の方でSNI SSLを取り急ぎ導入をされる方も多いと思います。

しかしWordpressではパッチが必要で、それについてはもう4年前に「さくらレンタルサーバーの共有SSLを使う」という記事で書きまして、SNI SSLでも同じパッチが使えるということで、多くのブロガーさんからピンバックを頂いています。

技術的なことはそちらを参照頂くとして、本稿では、先の項で紹介したWordpressのパッチについてのお話と、同じようなパッチを紹介されているブログにあった記述を思い出しながらつらつら書きたいと思います。

過去の記憶ですので、改めて調べて引用することは致しませんのでご了承ください。またもしかしたらそれらを書いているブログに対する苦言のように思われる方もいらっしゃるかもしれませんが、そのつもりは毛頭ありません。ノウハウをフリーで誰にでも参照できるようにされているということは、素晴らしいことだと思います。

またさくらインターネットさんの内部を妄想したりします。あくまでも妄想ですので、さくらインターネットさんとは一切関係ありません。(私も以前お客さんでサービス窓口を利用させていただいたのみです。)

さくらさんやらブロガーさんへの問い合わせについて

私のブログをご覧の方は、コメントで質問されるブロガーさんのほうがご覧になるのかな?しかし本章は質問する側の方へ、ということで書きます。

まずWordpressについてさくらさんやブロガーさんに「できない」と質問しても、メール、電話、コメント欄にて問題を直接解決するようなアドバイスを得ることは不可能です。

質問者のWordpressのバージョン、プラグインなどを再現して、原因を推測して解決法を得ることなどできませんから。

またWordpressの開発コミュニティーの人や、プラグインの作者も同様です。ましてやこれらの人は、さくらレンタルサーバー(或はXServer、ロリポップなども同様)を借りて試すこともできません。

もちろん親切なブロガーさんやコミュニティの中の方はアドバイスを下さると思います。しかし結局はオープンソースの運用は自己責任です。(それが嫌なら、お金を払えば対応しくれるところに頼みましょう。)

WordPressのさくらSSLパッチについて

ここから、すでにSSL対応された方へのつぶやきです。

「さくらレンタルサーバーでWordpressをSSLする場合はwp-config.phpに書きましょう」とされている以下のパッチについてです。

(さくらレンタルサーバーWordpress SSL/TSL対応パッチv.1.1)

if( isset($_SERVER['HTTP_X_SAKURA_FORWARDED_FOR']) ) {
	$_SERVER['HTTPS'] = 'on';
	$_ENV['HTTPS'] = 'on';
}

詳細は4年前の記事の最後の方をご参照ください。(繰り返しになりますが、さくらレンタルサーバーの仕様が変われば本稿のパッチのコードも効かなくなりますので、これまた自己責任です。)

さくらレンタルサーバーWordpress SSL/TSLパッチ 最新版:v.2.0 2017年6月19日

2017年6月19日現在の表題のパッチです。(もしかしたらもう必要ないかも。)

もっとよいやり方を考えられている方はいらっしゃると思いますので、Google先生と検討して下さいませ。もしよいやり方がありましたら、コメント頂けましたら幸いです。

主な改善点

v.1.1からの改善点は以下です。

  • サイトが’www.’付きURLで運用している場合に対応。(v.1.5より)
  • httpでのアクセスをhttpsにリダイレクトする処理を追加。
  • さくらレンタルサーバーでなくっても使えるようにコード。

2点目は、通常「.htaccessにて対応しましょう」と言われているところです。或いは、Wordpressのプラグインで対応されている方もいらっしゃるかもしれません。(プラグインで対応しようとした場合は、4年前の記事に書き、さらに以降のデバッグの章でも書いたような理由で、ドハマリする可能性があります。)

.htaccessが得意な人はそこで対応されればよいと思います。しかし私自身はもうmod_rewriteを覚えていませんし、また対応するなら一か所にまとめようと思ってPHPでリダイレクトを書きました。

3点目は、ある日突然さくらさんの仕様が変わって、通常になってもそこはかとなく動くようにとの願いを込めてですが、実際のところはどう変更されるかわかりませんので、うまくいかないかもしれません。

コード

v.2.0のパッチのコードは以下になります。

これまでと同様、wp-config.phpの「/* 編集が必要なのはここまでです ! WordPress でブログをお楽しみください。 */」の前の何処かに書いて下さい。

(さくらレンタルサーバーWordpress SSL/TSL対応パッチv.2.0)

$CNF_HOST_NAME = (substr($_SERVER['HTTP_HOST'], 0, 4)==='www.')? $_SERVER['HTTP_HOST']: 'www.'.$_SERVER['HTTP_HOST'];
//  If SSL/TSL on SAKURA
if( isset($_SERVER['HTTP_X_SAKURA_FORWARDED_FOR']) ) {
    $_SERVER['HTTPS'] = 'on';
    $_SERVER['HTTP_HOST'] = $CNF_HOST_NAME;
}
//  If not SSL/TSL or different host name, redirect.
if(!array_key_exists('HTTPS', $_SERVER) || $_SERVER['HTTPS']===''
    || $_SERVER['HTTPS']==='off' || $_SERVER['HTTP_HOST']!==$CNF_HOST_NAME) {
    header('Location: https://'.$CNF_HOST_NAME.$_SERVER['REQUEST_URI'], true, 301 );
    exit();
}

1行では、変数$CNF_HOST_NAMEに、あってほしいホスト名(FQDN)を設定します。ここではサイトを「www.」付のURLで運用している場合の例です。(Wordpressの一般設定にて、「www.」付のURLを設定してる、との意。)

$_SERVER[‘HTTP_HOST’]が「www.」付きならそのまま、そうでなければ「www.」を付けてあげています。(あ、日本語URLならmb_substrの方がよいかも。)

「www.」付きでないURLで運用している場合、1行は以下のようになるでしょうか。(試していないコードです。)

$CNF_HOST_NAME = (substr($_SERVER['HTTP_HOST'], 0, 4)!=='www.')? $_SERVER['HTTP_HOST']: substr($_SERVER['HTTP_HOST'], 4);

「www.」有り無しいずれの場合も、以下のように、ここに運用しているホスト名を直接書くことができます。

$CNF_HOST_NAME = "your-domain.com";

この場合のホスト名は、Wordpressに設定したものと同一にする必要があります。そうでないと100%リダイレクトループにはまりますのでご注意を。

3-6行が、さくらレンタルサーバーでhttpsでアクセスされた場合に通るブロックです。
4行で、以降のPHPプログラムがSSLだと認識できるようにしています。
5行では、$_SERVER[‘HTTP_HOST’]をあってほしいホスト名(FQDN)に書き換えています。

さくらレンタルサーバでは、ユーザーがSSL/TSLにて、「https://www.your-domain.com」のようにwww付きでアクセスした場合、$_SERVER[‘HTTP_HOST’]には「your-domain.com」のように、wwwなしのホスト名がセットされてしまいます。するとWordpress本体が「設定されているURLと違う」ということで「www.your-domain.com」にリダイレクトしてしまい、結果リダイレクトループになります。これを防ぐために、ここで無理矢理正しいホスト名に書き換えてあげています。

「www.」無しのURLで運用している場合は必要ありませんので、この行はコメントアウトしてください。

8-12行が、httpアクセスの場合および、アクセスされたURLのホスト名(FQDN)が、あってほしいホスト名と異なる場合の処理です。単に、httpsにてあらまほしきホスト名のURLにリダイレクトしています。

さくらレンタルサーバーの場合で3-6行を通った場合は、ここはスルーします。

8-9行のSSL/TSLの条件判断ですが、本当はwp-include/load.phpのis_ssl()の条件判断と一致させたほうが無難です。しかしそうすると長くなりそうですし、load.phpをここでrequire_onceするのも何かありそうな気がするので、ここではphp.netのマニュアルを読んで適当な条件判断にしています。

10行最後のステータスコード「301」は、もしかしたらブラウザがキャッシュしてしまうかもしれませんので、テストの段階までは「302」にしておいたほうが無難です。正常動作を確認した後に「301」にします。

またお気づきのように、このコードではさくらレンタルサーバーの場合での「https://your-domain.com」でのアクセスを、「https://www.your-domain.com」にリダイレクトすることはしません。
環境変数を眺めてみましたがいい手は思いつきませんでした。(´・ω・`)

よい手だてがありましたら、ご教示お願いいたします。

以上、v.2.0のパッチのコードと、ちょっと詳しい解説でした。

(ここに最新版を追記した関係で、以下の記事では同じことを繰り返し書いていたりします。適宜読み飛ばしをお願いいたします。)

なぜwp-config.phpに書くか

一応このパッチ(v.1.1)は、私が(私も)考えました。といっても簡単なパッチで、他の方でも思いつくでしょうから起源主張する気はございません。

4年前もWordpressのリダイレクトループを追っており、原因が環境変数$_SERVERと、is_ssl()の中での評価と気が付いてから、どこにパッチを当てるか考えました。

簡単にはis_ssl()の中でHTTP_X_SAKURA_FORWARDED_FORも評価してしまえば済みます。

しかしそうしてしまうと、忘れたころにWordpressをアップデートしたら、is_ssl()の修正はなくなるので、またリダイレクトループしてしまいます。

そこでアップデートしてもなくならない方法として気が付いたのがwp-config.phpにコードを書く、という手です。

この手は他にも使えて、.htaccessを書き換えなくてもURLパス($_SERVER[‘REQUEST_URI’])を修正してWordpressに処理させるとか、トリッキーに使えます。

パッチのコードを書く場所

どこかのブログで先のコードを「途中に書いたが機能しなかったので、先頭に書くこと」と書いてありました。

まあ先頭に書いても動作には間違いありません。

しかし「途中に書いたが機能しなかった」というのは、既に環境変数をゴリゴリ弄るようなwp-config.phpで、その既存のコードに干渉したのでしょうか?

私は、configは整然と定義(wp-config.phpではdefine)が並ぶことを好みますので、パッチのコードは後ろの方「/* 編集が必要なのはここまでです ! WordPress でブログをお楽しみください。 */」の前に書いています。(このコメントが英語とか他の言語の場合も。)
もちろんそのコメントの後でも構いませんし、究極は「require_once(ABSPATH . ‘wp-settings.php’);」の前であれば構いません。(その前のif文の直後はダメですね。)

ちなみに、Wordpress本体はここのwp-settings.phpから動きます。

$_ENVの設定は必要か

is_ssl()の中では$_SERVERしか参照していないので実は必要ありません。

4年前に入れたのは、自分や他のプラグインが参照したりしたときの保険のつもりでした。

www付きURL運用パッチについて

さくらレンタルサーバーでWordpressのサイトを「www.hoge.com」のようなwww付きのURLで運営している場合の、SSL用のパッチです。

(さくらレンタルサーバーWordpress SSL/TSL対応パッチv.1.5)

if( isset($_SERVER['HTTP_X_SAKURA_FORWARDED_FOR']) ) {
    $_SERVER['HTTPS'] = 'on';
    if( substr($_SERVER['HTTP_HOST'], 0, 4)!=='www.') {
        $_SERVER['HTTP_HOST'] = 'www.'.$_SERVER['HTTP_HOST'];
    }
}

このパッチは他のブログを幾つか参照させて頂きました。(ありがとうございます。m(_ _)m。)

私なりのコードに変えています。(その理由は先の記事にて。)

ドメイン名?

読ませていただいたブログ記事の中では「ドメイン名」を書くように指示しているものがありました。

こんなかんじ。($_ENVの設定もありましたが省略。)

if( isset($_SERVER['HTTP_X_SAKURA_FORWARDED_FOR']) ) {
    $_SERVER['HTTPS'] = 'on';
    $_SERVER['HTTP_HOST'] = 'ドメイン名';
    $_SERVER['SERVER_NAME'] = 'ドメイン名';
}

ふと疑問に思ったのは、例えばWordpressを「www.hoge.com」で運用していた場合、ドメイン名は「hoge.com」で、「www.hoge.com」はサブドメインだと思っている人が勘違いするのでは?ということです。

もしかしたら各ブログはそう勘違いしないように「ドメイン名は~」と説明があったかもしれません。

ここで私の、先のブログを見返すと「ホスト名」と書いていました。

これも釈然としないので調べてみると、ホスト名は「www」、ドメイン名は「hoge.com」、FQDNは「www.hoge.com」ということです。

しかもFQDNを指して「ホスト名」「ドメイン名」と書いている場合もあるから気を付けましょう、と。

一応URLを規定しているRFC 1738をみましたら、3.1節にて当該部分を<host>と表現しており、説明には「host  The fully qualified domain name of a network host, or its IP address(以下略)」とありました。

「FQDN」ではまたわからない方もいるでしょうから、「ホスト名(FQDN)」「ドメイン名(FQDN)」「FQDN(ホスト名.ドメイン名)」のような書き方がよいのでしょうね。(反省)

$_SERVER[‘SERVER_NAME’]の設定は必要か?

私が先のパッチを書いた時は「サーバー名はxxx.sakura.ne.jpだろ~」と思って書きませんでした。(実際リダイレクトループはなくなります。)
これまた改めてPHPマニュアルの$_SERVERのページを見ますと以下のようにあります。

‘SERVER_NAME’
現在のスクリプトが実行されているサーバーのホスト名です。 スクリプトがバーチャルホスト上で実行されている場合は そのバーチャルホスト名となります。

バーチャルホストなら保険で書いておいてもよいかもしれません。その直後にこうも書いてありますから、参照しているプログラムは多くはないかも。

注意: Apache 2 では、UseCanonicalName = On と ServerName を設定する必要があります。 そうしなければ、この値はクライアントが提供するホスト名を指すようになってしまい、無意味です。 また、セキュリティ的な意味合いでこの値に頼ってはいけません。

リダイレクトループの時のデバッグ

つづいて、リダイレクトループではまってしまったときのデバッグ方法について書きたいと思います。

リダイレクトさせないツール

ブラウザからアクセスすると素直にリダイレクトループにはまってしまうのでよろしくありません。
こんなとき、年季の入った方は「telnetでたたけばよい」とおっしゃるでしょう。
しかし私はtelnetでHTTPでたたいたことはめったにないでしすし、ましてやHTTPSがたたけるのかは謎です。
4年前にはまったときは、Firefoxにリダイレクトさせないというアドオンがありましたので、それを使いました。
Chromeなどにもあると思いますので、もし必要であれば探してみて下さい。(私も必要になったときに改めて探します。)
これをONにしてブラウザのデベロッパーツールのNetworkタブを使えば、現象が把握できます。

誰がリダイレクトさせるか?

おおよそリダイレクトさせる人としては、以下が考えられます。

  • Apache本体(httpd.conf)
  • .htaccess
  • WordPress本体
  • WordPressのプラグイン

この中の一人がさくらレンタルサーバーのような仕様によって、或はユーザーの設定ミスによって、一人でリダイレクトループしている場合があります。(壁打ちテニス。)
またこれらの中の二人が、自分の設定を主張するリダイレクトをして、結果ラリーのようなリダイレクトループになっていることもあります。
この場合は、先のリダイレクトさせないアドオンをオフにして、デベロッパーツールのNetworkを見るとラリーをしているのが見えるかもしれません。

個別のデバッグ法

.htaccessとか、wp-config.phpのパッチとか、設定をいっぺんにしてしまうと、誰が悪さをしているのかわからないので、ひとつづつ外していくことをお勧めします。
本節では、その一つづつの検証のしかたを書きたいと思います。(とはいえ、全てではありませんので各位工夫してください。m(_ _)m)
一つ目のApache本体については、レンタルサーバーのユーザーはさわれないので、ここでは書きません。これが原因であることも多くはないでしょう。

.htaccessを疑う

「(SEOのために)常にhttps://wwwでアクセスされるようにしましょう」と、.htaccessを編集した場合はこれを疑います。編集前のバックアップがあれば、戻します。
またWordpressのディレクトリの中にある「readme.html」などにアクセスしてみてリダイレクトループするようでしたら、原因はWordpress以下である可能性は低いと言えます。

プラグインを疑う

次にプラグインを外すことから考えます。
管理画面もリダイレクトループで見えないかもしれません。(さくらレンタルサーバーwww付きのように、トップページのみリダイレクトループで管理画面が見える場合もあります。)
取りあえず、FTPでディレクトリ./wp-content/pluginsのなまえを「plagins.hoge」とかすれば、プラグインは全部読み込めなくなります。
これで現象がなくなるのであれば、pluginsの名前を戻した後に、個別に怪しいプラグインのディレクトリ名を変えていけば(或はローカルにバックアップして削除していけば)そのうち当たるかもしれません。

WordPressを疑う

最後にWordpressのデバッグですが、これは困難。
お仕事のSIer、プログラマーさんはオンラインデバッガでデバッグするのでしょうが、ここは原始的にprintf、でなくて「echo (変数名); exit;」。
これを書いてはアクセス、書いてはアクセスして原因を絞ります。
しかしWordpressの構造をある程度知っているプログラマーでないとできません。
私もやりたくありません。

さくらさんの気持ち

4年前の記事に最近追記を行い以下のように書きました。

ただ、レンタルサーバーでWordpressという環境、及び追記冒頭のSSL/TLSの需要を考えると、さくらさんがいつまでもこのようなパッチが必要な環境にしておくわけないだろ?と思います。

とはいえ、少なくとも4年前のままですので、変わらないような気もします。(このように書いたのは、読まれた方がご自身で調べるように、との願望もあります。)

さくらインターネットの公式パッチがない理由

私がパッチを作れるくらいですからさくらさんも可能でしょうし、公式に公開されれば私の記事もさほどピンバックされなかったでしょう。
なぜさくらさんは公式パッチを公開しないのでしょうか?

最近知人から、表題の興味深い推測を聞きました。
曰く「公式パッチを書いてしまうと、ユーザーから不具合のように思われてしまうから書かないのではなかろうか?」

面白いですね。
そういえば4年前、レンタルサーバーをいろいろ探しているときに、あるレンタルサーバー屋を推奨する、明らかにサクラのブログ(さくらインターネットさんではありません。ステルスマーケティングの意味のサクラです笑。以降カタカナで書きます。)をたくさん見ました。
もし公式に書いてしまうと、そういった競合のステマに餌をあたえるようなものですね。
しかしそのようなブログをサクラのブログ、ステマだと推測されてしまえば、逆マーケティングです。私もそのようなブログの褒めるレンタルサーバーは候補から除外です。

ステルスサポート

とはいえ、私のブログのようないつの記事かわからない情報がいつまでも参照されるのは考えものです。
そこでステルスマーケティングならぬステルスサポートを考えました。
略して「ステサ。」
ステマは忌み嫌われますが、ステサはばれてもそうはならないはず。

方法は簡単で、ユーザーであるブロガーとして、適切なパッチをリアルタイムで記事にし、昔の記事は適切に追記するだけ。
そしてSEOして他の記事よりトップに来るようにする。
たまに技術情報もユーザーとしてそれとなく記事にする。
サポートにきた質問には「とあるユーザーの方」といってそれとなく紹介する。
(もしかしてすでにどこかやっているかもしれません…)

おわりに

書き殴っていたらいつものような長文になりましたね。
ここまで読む人はいるのかしらん?

コメントを残す