WordPressでxmlrpc.phpのDDOS攻撃を回避する nginxでPOSTメソッド対策

この度、私が使っているお名前.com VPS がここ数週間、障害に見舞われ数時間停止してしまいます。
毎回、サーバーを再起動して運用しておりました。

お名前.comのVPSについては、以下をご覧ください。
WordPressの引越し さくらVPSからお名前.comのVPSへ

さて、障害発生時のお名前.comのコントロールパネルから見たリソース情報は以下の通りです。

image

Disk I/Oが異様に高くなっていることが分かります。

ここ1週間のリソース情報は次の通りです。

image

時々、Disk I/Oが異常に高くなっているのが分かりますが、これが障害が発生したタイミングです。

障害発生時には、Uptimer Robotからの監視メールが送られるようになっており、メールで異常を発見しサーバーを再起動していました。

Uptimer Robotについては、以下をご覧ください。
さくらインターネットのVPS(仮想専用サーバー)のサーバー・ネットワークの監視(リソース情報、Uptime Robot)

今回、この障害の原因を調査して対策を行いました。
スポンサーリンク

nginxのアクセスログから原因を調査する xmlrpc.phpが攻撃対象

サーバー運用での基本は「エラー・障害原因をログから調査する」です。

nginxのアクセスログを調べてみます。
すると、以下のように、xmlrpc.phpにPOSTする行が大量に吐かれていることを見つけます。

それこそ、1秒に3回ぐらい発行されています。

これは典型的なDDOS攻撃です。

DoS攻撃(ドスこうげき、ディーオーエスこうげき、Denial of Service attack)とは、サーバなどのネットワークを構成する機器に対して攻撃を行い、サービスの提供を不能な状態にする攻撃をいう。 サービス妨害攻撃などとも呼ばれる。ゾンビコンピュータを利用した分散型で行う場合は、DDoS攻撃(ディードス攻撃)と呼ばれる。

DDoS攻撃(ディードスこうげき、ディーディーオーエスこうげき、Distributed Denial of Service attack)とは、踏み台と呼ばれる多数のコンピュータが、標的とされたサーバなどに対して攻撃を行うことである。別名として、協調分散型DoS攻撃分散型サービス妨害攻撃などがある。

単一のホスト(通信相手)からの攻撃ならばそのホストとの通信を拒否すればよいが、数千・数万のホストからでは個々に対応することが難しい。したがって、通常のDoS攻撃よりも防御が困難であり、攻撃による被害はDoS攻撃よりも大きくなると考えられる。攻撃を受けたサーバには踏み台となったコンピュータが攻撃主として認識される。
(wikipediaより)

WordPressのxmlrpc.phpをdeny allにすると、403(Forbidden)

WordPressのxmlrpc.phpというファイルは、外部エディタを使ってブログに書き込んだりするために使われるファイルです。
そのため、Windows Live WriterとかMarsEditのような外部エディタを使っていない人には、このファイルは関係ありません。

そこで、nginx.confから呼ばれるconfファイルに以下の設定を行い、再起動してみます。

こうすれば、DDOS攻撃は回避されます。

ちなみに、access_log offとerror_log offを入れておかないと、下記のように大量の403(Forbidden)がログが吐かれてしまいます。

(注意 2015/10/29)
上記のように設定すると /etc/nginx に off というファイルが作成されて、大量のアクセスログが生成されてしまいました。
そこで以下のように変更しました。

access_log /dev/null;
error_log /dev/null;

対策が万全であれば、access_log offとerror_log offを入れておくことがよいです。

ところで、この設定だと、Windows Live Writerが使えません。
Windows Live Writerでブログに投稿しようとすると、以下のメッセージが表示されます。

image

ログイン中に予期しないエラーが発生しました。
サーバーエラー - 以下のWebアドレスについてサーバーエラーが発生しました。

http://xxx/xmlrpc.php
403 Forbidden

まぁ当然ですね。これだと不便です。

allowでIPを許可してみると405 Not Allowed

そこで、confファイルを以下のように変更します。

Apacheと異なり、nginxでは上記のように許可するIPアドレスを先にallowで指定して、その後で、deny allします。
deny allを先に書いて、後でallowを行うと、deny allの方が優先されてしまい、すべてdenyとなってしまいます。

上記の設定を行い、Windows Live Writerで投稿しようとすると以下のようなメッセージが表示されます。

image

ログイン中に予期しないエラーが発生しました。
サーバーエラー - 以下のWebアドレスについてサーバーエラーが発生しました。

http://xxx/xmlrpc.php

405 Not Allowed

うーん。。。そこで、今度は以下のように405を200に変更してみました。

すると以下のメッセージが表示されました。

WS000160

ログイン中に予期しないエラーが発生しました。

サーバーの応答が無効です - ブログサーバーから受信した
blogger.getUsersBlogs メソッドへの応答が無効です。

Invalid response document returned from XmlRpc server

このアプローチではダメなので別の方法を探します。

proxy_passでバックエンドに転送すると500 Internal Server Error

そこで、confファイルを以下のように変更します。
proxy_passを使ってバックエンドのfactcgiに転送します。

この設定で、Windows Live Writerを使ってブログに投稿してみると、500 Internal Server Errorとなりました。

ログを表示する設定に変更して、エラーログを見てみました。

Too many open files ?

ファイルディスクリプタが足りない?っていうことでしょうか。

ファイルディスクリプタを増やしてみても502 Bad Gateway

そこで、以下の設定を行います。

/etc/security/limits.confを編集します。最後の行の一つ手前に以下の行を追加します。

この設定を行うことにより、システムのファイルディスクリプタの上限値、ulimit -nで表示される値を変更します。

設定を変更後、exitとしてから再度、ログインするか、または、su -すると変更が反映されます。

ついでに/etc/nginx/nginx.confの以下の行の値を変更しておきます。

この後、nginxを再起動します。

この設定で、Windows Live Writerを使ってブログに投稿してみると、以下のエラーが表示されました。

image

ログイン中に予期しないエラーが発生しました。

サーバーエラー - 以下のWebアドレスについてサーバーエラーが発生しました。

http://xxx/xmlrpc.php

502 Bad Gateway

ログを表示する設定に変更して、エラーログを見てみると以下のように表示されていました。

4096 worker_connections are not enough

さすがにこのエラーは違うだろう。。。

まとめ

nginxでWordPressを使っていて、xmlrpc.phpを自分のアクセス元だけ許可するっていう設定なら、どこでもありそうなんですが、同じ悩みを持っている人いませんか。ちょっと困っています。
現在、Windows Live Writerが使えなくて不便しています。
引き続き調査します。

最後まで読んでいただきありがとうござました。
この記事が気に入っていただけたらシェアしてくれると嬉しいです。

スポンサーリンク
スポンサーリンク
Translate »