ことの起こりは数日前。
最近頻発するLightsailの高負荷状態を調査するため、すべてのWordpressプラグインを無効化したことから。
XMLRPCにアクセスできない
多くのプラグインはすぐ有効化できました。
Wordpress純正の複合プラグイン“Jetpack“以外は。
有効化したのちサービスの初期設定を行いますが、「Jetpackを設定」を押してもエラー表示で先に進めません。
The Jetpack server was unable to communicate with your site https://dolls.tokyo [HTTP 403]. Ask your web host if they allow connections from WordPress.com. If you need further assistance, contact Jetpack Support: http://jetpack.com/support/
原因のほとんどはxmlrpc.phpにアクセスできない事によるものらしい。
xmlrpc.phpは外部ツール・サービスとWordpressを繋ぐ窓口となるスクリプトです。
Wordpressインストール時にルートフォルダ直下に置かれるもので、その性質上良く攻撃のターゲットにされるため普段は無効化する事が推奨されます。
自分も過去の構築時に塞いでおり、アクセスがブロックされていました。
それは分かったものの、どこでブロックしているのが分からない。色々な記事の手順をよく理解せず構築した結果です。
結局解決までに丸一日を費やしました。
もし同じ事態になっているひとがいたら、チェックすべきポイントを紹介します。
htaccess.confで全拒否
この設定が入っていると、ファイルへのアクセス自体を蹴ります。
Forbidden
You don’t have permission to access this resource.
今回.htaccess自体に記述はありませんでした。
しかし、bitnami環境で参照されるコントロールファイルに該当あり。
vi /home/bitnami/apps/wordpress/conf/htaccess.conf <Directory "/opt/bitnami/apps/wordpress/htdocs/"> <Files xmlrpc.php> Order allow,deny Deny from all </Files>
一旦<Files xmlrpc.php>~</Files>をすべて消し、Apacheを再起動します。
sudo /opt/bitnami/ctlscript.sh restart apache
この結果、メッセージは変わりましたがまだダメ。
mod_rewriteで0.0.0.0に飛ばす
mod_rewriteを使い、xmlrpc.phpにきたアクセスを全て無害な0.0.0.0へ転送していました。
このmod_rewriteを使う方法は非常に多くのサイトで紹介されています。
自分はhttps化の時に、転送ルールの一つとして追加していました。
徒労日記のhttps化 ~ Let’s Encryptの無料証明書でnginx上のwordpressを常時SSLに対応させる
この手法による対策は、DoS攻撃を受けた際にhttpdが処理するためCPU負荷が上がってしまうとの事。
.htaccessで止めるのがベターなので使わない事にします。
vi /opt/bitnami/apps/wordpress/conf/httpd-app.conf <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteRule ^xmlrpc\.php$ "http\:\/\/0\.0\.0\.0\/" [R=301,L] ← 削除する RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] </IfModule>
RewriteRule ^xmlrpc\.php$~の行を削除しました。
またApacheの再起動を行います。
2021/02/08 追記
処理の負荷についてしらべると、このmod_rewirteで処理した方が単純にDeny from allするより良いという意見が強いようです。
「このURLは0.0.0.0である」と一度クライアントにキャッシュさせる事により、以降のアクセス自体を無くすのだとか。
悪意をもってアクセスする側がブラウザなんかを使うかは懐疑的ですが、一応このRewriteRuleを復活させました。
ブラウザキャッシュ
初歩的で恥ずかしい事ですが・・・。
問題の0.0.0.0画面がブラウザキャッシュに残り、サーバ側が問題を解消していた時も古いエラー画面を見続けてしまいました。
ハマっている時ほど、そういう基本的なチェック前処理を忘れがちです。
調査環境になっているブラウザを終了させたくない心理もその原因の一つ。
結局、Chromium化したEdgeをきれいサッパリ掃除し、それで確認したらxmlrpcアクセスが通るようになってました。
あらかじめ結果測定だけは別ブラウザで見るのも一つの手段です。
SiteGurdでブロック
WordPressのセキュリティプラグインSiteGuard WP Plugin | ソフトウェアWAFのJP-Secure。
ここに”XMLRPC防御”があります。
これを有効にすると.htaccessが編集され、xmlrpc.phpへのアクセスがコントロールされます。
ようやくアクセス成功
これらを見直し、ようやくxmlrpc.phpへのアクセスが通りました。
XML-RPC server accepts POST requests only.
しかし、まだ終わらなかった。
承認時にcURL error 60
xmlrpc.phpのアクセスが成功したものの、サービスへの接続にまだ失敗する。
Something went wrong.
cURL error 60: SSL certificate problem: unable to get local issuer certificate
もう一度やり直す
Jetpack サポートに連絡する
不完全な証明書チェーン
これについて調べると、事例発見。
試しにLet’s Encrypt導入時にも行ったSSL Server Testでテストしてみます。
当時自前サーバ(nginx)環境では”A”だった結果が”B”になってる(画像は解消後のもの)。
そこに書かれていた理由がこれ。
This server’s certificate chain is incomplete. Grade capped to B.
(意訳:このサーバは証明書チェーンが不完全です。なのでBグレードです。)
そしてこのチェーンがincompleteだと、今回のエラーになるとの事。
Jetpack cannot connect (cURL error 60: SSL certificate problem) | WordPress.org
This is because our server cannot verify your server’s SSL certificate, as its chain is incomplete.
fullchain.pemを証明書として使用する
このimcompleteをどう解消するか。
色々な事を調べすぎてエビデンスを示せないのだけど、サーバはLet’s Encryptにて取得した最新のfullchain.pemを利用すれば良いらしい。
そして現在の環境をしらべたところ、単体の証明書しか使っていない事が判明しました。
これは過去の構築で作った証明書の更新&配置スクリプト。
vi /usr/local/bin/letsencrypt/renew-cert.sh #!/bin/sh /usr/local/bin/letsencrypt/certbot-auto renew sudo cp /etc/letsencrypt/live/dolls.tokyo/cert.pem /opt/bitnami/apache2/conf/server.crt sudo cp /etc/letsencrypt/live/dolls.tokyo/privkey.pem /opt/bitnami/apache2/conf/server.key sudo cp /etc/letsencrypt/live/dolls.tokyo/fullchain.pem /opt/bitnami/apache2/conf/server-ca.crt sudo /opt/bitnami/ctlscript.sh restart apache
fullchain.pemはserver-ca.crtにコピーしています。
しかし、証明書として使用されているのはserver.crt=元cert.pemのみ。
Apacheは2.4.8から中間証明書ファイル(server-ca.crt)を指定する宣言が無くなり、SSLCertificateFileに両方が入った証明書を指定する必要があるそうです。
$ cat /opt/bitnami/apache2/conf/bitnami/bitnami.conf <VirtualHost _default_:443> DocumentRoot "/opt/bitnami/apache2/htdocs" SSLEngine on SSLCertificateFile "/opt/bitnami/apache2/conf/server.crt" SSLCertificateKeyFile "/opt/bitnami/apache2/conf/server.key"
という訳で更新&配置スクリプトを修正し、fullchain.pemをserver.crtとするように変更。
vi /usr/local/bin/letsencrypt/renew-cert.sh #!/bin/sh /usr/local/bin/letsencrypt/certbot-auto renew sudo cp /etc/letsencrypt/live/dolls.tokyo/privkey.pem /opt/bitnami/apache2/conf/server.key sudo cp /etc/letsencrypt/live/dolls.tokyo/fullchain.pem /opt/bitnami/apache2/conf/server.crt sudo /opt/bitnami/ctlscript.sh restart apache
fullchain.pemは証明書cert.pemと中間証明書chain.pemを内包します。
ようやく復旧
こうしてようやくJetpack復旧にこぎ着けました。
一時諦めも考えましたが、無料の画像CDNと投稿時のSNS宣伝に実は頼っていた事を実感。
どうにか復旧を目指しました。
今後のxmlrpc.phpへのアクセスコントロールはSiteguardプラグインを使おうと思います。
.htaccessへの下記編集をGUIでしてくれるようなので。
#SITEGUARD_PLUGIN_SETTINGS_START #==== SITEGUARD_DISABLE_XMLRPC_SETTINGS_START <Files xmlrpc.php> <IfModule authz_core_module> Require all denied </IfModule> <IfModule !authz_core_module> Order allow,deny Deny from all </IfModule> </Files> #==== SITEGUARD_DISABLE_XMLRPC_SETTINGS_END #SITEGUARD_PLUGIN_SETTINGS_END