某国際機関のウェブサイト制作を引き受けることになり、CMS導入を希望されたのでお手軽WordPressで構築しようとしたのですが。
いかんせんお相手は某国際機関(‥ってどこやねん!というツッコミはおいといて)のウェブサーバーにWordPressを入れることは、色々と大変でして(手続き、承認、セキュリティ、‥ウンヌンカンヌン)。
そこでReverse-Proxyを先方にて用意していただき、我々は別サーバー上にWordPressサイトを作ってReverse-Proxyにて接続してもらう、という事になりました。
しかしながらうまく動作せず、ハマってしまいました。
ググってみましたが、意外な事に情報が見つからず。
最終的には自己解決したので、その内容をシェアいたします。
Reverse-ProxyとWordPress、それぞれの関係性を例示します
ウェブブラウザーからアクセスするURLが「 https://sample.site/blog/ 」(A)
Reverse-Proxy がアクセスするURLが「 https://origin.site/samplesite_blog/ 」(B)
(A)にReverse-Proxy が搭載されています。
(B)にWordPressが存在します。
このような関係性です。
(B)のWordPress側では以下に記載の通り設定を行います
https://ja.wordpress.org/support/article/faq-installation/#リバースプロキシを使用している場合
他には、(B)の出力、特にリンクを変えるために、以下の設定を wp-config.php 先頭部分に追記します。
define('WP_SITEURL' , 'https://sample.site/blog/');
define('WP_HOME' , 'https://sample.site/blog/');
define('WP_CONTENT_URL', 'https://sample.site/blog/wp-content');
というところまでは、あちこちで紹介されているのですが。
‥はい、失敗します。
WordPress側に必要な事は「パスを合わせる」
(B)のURLを、「 https://origin.site/blog/ 」(B’)
としてください。
パスの部分「/blog/」を(A)と(B)で同じにする、という事です。
理由は私も明確に説明できませんが。
WordPressは、REQUEST_URIに含まれるパスとローカル上のパス(この場合は /blog と /samplesite_blog )が異なる時に、パスが違うと判断するようです。
これはパーマリンク設定を ?p=xxx 以外にしたときに発生します。
どのページを開いても 404 Not Found となってしまうのです。
基本的にはこのお約束を守ってもらえれば大丈夫です。
以下は、あらかじめそうせず、相手に違う情報を伝えたため何とか自力だけで何とかしようと、小手先の技で逃げ切った事例ですので、参考にはならないと思いますが、「こういう手もあるんだ」程度に見てもらえたら、と思います。
Reverse-Proxy側でリクエスト先を変えてもらうのが難しい場合
(B)を(B’)にすること自体は、WordPress側で簡単にできます。
でも、Reverse-Proxyを設定している(A)側にも、(B)が(B’)に変わったよ、と言わないといけない。
そう言ってすぐ対応してくれるのなら何の問題もないのですが、いかんせんお相手は某国際機関(ってどこ??)。
手続きが大変で、変更に時間がかかると申すのです。
だから何とかしてWordPress側だけでパスを変える必要があったのです。
WordPress側のパスを、このような方法で変えました
結論、こうしました。
wp-config.php(先頭部分) に以下の設定を追記しました。
$_SERVER["SCRIPT_NAME"] = str_replace("/samplesite_blog","/blog",$_SERVER["SCRIPT_NAME"]);
$_SERVER["REQUEST_URI"] = str_replace("/samplesite_blog","/blog",$_SERVER["REQUEST_URI"]);
WordPress側でURLを置換して、(A)のパスと同じにしました。
でもまだ足りません。
サーバー内のパスは、相変わらず /samplesite_blog のままです。
そこで、このようにしました。
2案ありますが、どちらか採用しやすい方法でOKです。
案1 WordPressインストールディレクトリを変更する
・WordPressインストールディレクトリを、/samplesite_blog から /blog に変更(リネーム)する。
・ルートディレクトリ上の.htaccess で、 RewriteRule を使い、 /samplesite_blog を /blog に向くよう設定する。
RewriteRule ^samplesite_blog(.*)$ /blog$1
案2 シンボリックリンクでパスを見かけ上あわせる
・WordPressインストールディレクトリを、/samplesite_blog から /blog に変更(リネーム)する。
・シンボリックリンクを張る。
$ ln -s blog samplesite_blog
こんなかんじです。
これで無事期待通りの動きとなりました。
めでたしめでたし。
SEO対策として必要な事
基本これでOKですが、SEOの観点で考えると、(A)と(B)どちらのURLからアクセス出来てしまう事はよろしくありません。重複コンテンツとなるからです。
なので、(B)からのアクセスは一切許可しないようにしました。
やり方は色々ありますが、今回は wp-config.php に以下の記述をすることで対応しました。
if ( @$_SERVER['REMOTE_ADDR'] != 'xxx.xxx.xxx.xxx' ) {
header("HTTP/1.1 401 Unauthorized");
exit;
}
xxx.xxx.xxx.xxxは(A)のIPアドレスです。
ここからのアクセス以外をすべて拒否する設定です。
もっとシンプルに、.htaccessなどウェブサーバー側で行っても良いです。
今回 wp-config.php に記述したのは、デザイン会社さんなど別のところが.htaccessを触る可能性があるので、万が一設定を消されても良いようにした、というのがその理由です。
これで、一通り動くようになりました。
改めて、めでたしめでたし。
多段Reverse-Proxyで起きた問題への対応(2023.02.27追記)
設定を行ってから数日後、動作確認をしていたところ特定のURLでリダイレクトが発生し、しかもその時のホスト名が(B)のorigin.siteになってしまい、焦った事がありました。そのための対策も既にしていたはずなのに・・。
具体的にはこういう設定をしていました。
$_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
WordPressは、HTTP_HOST‥つまりリクエストされたホスト名を使って、コンテンツ中のリンクやリダイレクト先URLなどを内部で生成しています。
通常だとウェブブラウザーで指定されたホスト名とHTTP_HOSTは一致します。
Reverse-Proxyを経由する場合、つまりホストAからホストBにリクエストするときは、ホスト名Bが HTTP_HOSTにセットされます。つまりウェブブラウザーで指定されたホスト名とHTTP_HOSTは一致しません。
リダイレクト先URLを適切に作ってもらうには、ウェブブラウザー上で指定されたホスト名を、WordPress上に渡してあげる必要があるわけです。
下の引用先を見てもらうと分かる通り、WordPressからみたときに、Aのホスト名は通常HTTP_X_FORWARDED_HOST ヘッダーに載っていることが分かりますから、上のコードを書いてください、という話はごもっとな話です。
X-Forwarded-Host (XFH) ヘッダーは、 HTTP の
Host
リクエストヘッダー内でクライアントから要求された元のホストを特定するための事実上の標準となっているヘッダーです。https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Forwarded-Host
さて、そんな前提を知っていただいたうえで。
改めて (B)にリダイレクトされた原因について調べたところ、HTTP_X_FORWARDED_HOST に入っている値が正しくなかった、という事がわかりました。
では、誰がこの値を設定した?
最初はホストB(WordPressを搭載したサーバー)である、Xserver側ではないかと思いました。
Xserver側では既にReverse-Proxyを立てられていて、アプリケーションサーバー(例えばphp-fpm)に処理を引き継いでいるように見えるからです。その時に正しくHTTP_X_FORWARDED_HOST を指定しなかったのではないか、とという推測です。
でも、ここまで書いてふと思ったのです。
ホストA(某国際機関のReverse-Proxy)を設定した人のミスかもしれないかも‥。むしろこっちの可能性が高い気がしました。
とはいえ、しつこいですが相手に言いづらい‥というか、いうとやぶ蛇になりそうだったので、そこを持ち出す事はしませんでした。
要は、HTTP_X_FORWARDED_HOST の値が期待値ではない場合は使えないし。それを設定する相手に責任を押し付けてもしょうがないし、押し付けても面倒な未来しか見えないし。
だったら別の方法で HTTP_HOST を変えてしまえば良いよね、という結論に達し、このように直しました。
$_SERVER['HTTP_HOST'] = 'sample.site'; // (A)のホスト名
これで無事、リダイレクト時に(B)のホスト名に行く事が無くなりました😅
ちなみに、どういうときにリダイレクトが発生するのか。
例えばこれです。
https://sample.site/news
↓
https://sample.site/news/
最後に「/」があるかどうか、です。
なぜここが原因か、と特定出来たのかというと。
ただひたすらリダイレクトが走った処理を追っかけて行ったからです。
ちなみに、 wp-includes/canonical.php がこれを行っていました。
canonical といえば 正規のURLにするってもの。
WordPress的には /new は NGで /news/ が正規のURLなのですね。
ということで、そもそもHTMLコーディング時に指定したURLをきちんとしておけばよい、という判断でHTMLコーダーさんに依頼してURLを直してもらいました。
WordPress側で 正規のURLに変えてくれるならいいじゃない、と思うでしょうが。
URLを変える、という事はブラウザー側でもう一度正規のURLにアクセスしなおす、という処理が発生するという事でもあります。もう一度アクセスする、という事は通信も2回発生するわけですし、その間の表示に時間がかかるのはもちろん、トラフィックも無駄に増えてインターネットにご迷惑をおかけする、という事です。
(そういえばトラフィックを増やすな、とか昔はよく言ってたけど、最近はめっきり言わなくなりましたね)
少なくとも、表示に時間がかかるという事は、訪問に来た人にとって決して良い体験を与えるものではありません。下手したら離脱されかねません。
Googleさんも表示速度については重要視していて、SEO上大事だとも言ってます。
少しでも表示を速くしてユーザー体験をよくすることは、私たちプロフェッショナルの務めだと思っています。
IT相談役始めました
当社では、システム開発やサイト制作以外にも、システムにまつわる様々な相談をお受けしております。
・システム導入を検討しているが、ITに詳しい人間が社内にいないから判断がつかない。
・社内SEを育成したい。技術的な事で相談したい。
・ウェブサイトで集客をしたいがどうすればよいかわからない。
・システム業者、ウェブサイト制作業者の言っている事が正しいかどうかわからない。
システムにまつわる様々な相談を毎月のサブスクリプション契約でお受けするサービスです。
最初は単発で相談をいただいていましたが、問題になる前に解決出来た方がよく。
そのためには継続した関りが必要なので、毎月のサブスクリプション契約としました。
気軽に相談できる環境が良いと思い、月1万円で行っております。
初回のご相談は無料ですので、お気軽にお問合せ下さい。