掲題の情報は、
EN-PC Service の 社員ブログ saito氏の 2023/02/21 の情報です。
サイトがなくなった時の為に、メモ化します。
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側では以下に記載の通り設定を行います
他には、(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インストールディレクトリを、/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)でもアクセス出来てしまう事はよろしくありません。重複コンテンツとなるからです。
なので、(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はWordPressが動いているホスト名(B)です。リダイレクト先URLを作るのであれば、クライアント(ウェブブラウザー)上で指定されたURL(A)のホスト名を使わないといけません。
URL(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 に入っている値がそもそも正しくなかった、という事がわかりました。
じゃあ誰がこの値を設定したの?という話ですが、おそらくWordPressを搭載したサーバーである、Xserver側ではないかと推測しています。というのは、Xserver側では既にReverse-Proxyを立てていて、アプリケーションサーバー(例えばphp-fpm)に処理を引き継いでいるように見えるからです。その時に正しくHTTP_X_FORWARDED_HOST を指定しなかったのではないか、とという推測です。
‥いやまてよ、ここまで書いてふと思ったのですが。某国際機関の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にするってもの。
そう、 /new は NGで /news/ が正規のURLなのです。
ということで、そもそもHTMLコーディング時に指定したURLがいけないので、コーダーさんに依頼して直してもらいました。
WordPress側で 正規のURLに変えてくれるならいいじゃない、と思うでしょうが。
URLを変える、という事はブラウザー側でもう一度正規のURLにアクセスしなおす、という処理が発生するという事でもあります。もう一度アクセスする、という事はその間表示に時間がかかるという事です。