目次
背景
ある日、WordPressで作っているサイトにアクセスすると、突然表示されなくなりました。
ブラウザには「ERR_CONNECTION_REFUSED」。
SSHではサーバーに入れるのに、Webだけ死んでいる状態です。
最初はよくあるパターンで疑いました。
- WordPressの不具合?
- プラグイン更新ミス?
- PHPエラー?
結論から言うと、どれも違いました。
原因は「サーバーのメモリ不足(OOM)」でした。
環境
- OS:CentOS系
- Webサーバー:Apache(mpm_prefork)
- PHP:8.1系
- メモリ:約487MB(VPS)
- CMS:WordPress
原因
ログを追うと、次の事実が分かりました。
- httpd が
oom-killerによって強制終了されている - xmlrpc.php に対して大量のPOSTリクエスト
- 同一IPから数秒おきにアクセス
つまり今回の原因は👇
xmlrpc.phpへの攻撃 → PHP処理増加 → メモリ枯渇 → Apache停止
WordPressのバグではなく、攻撃+リソース不足の組み合わせでした。
試したこと
① Apacheの状態確認
systemctl status httpd
結果:failed / killed
→ 自発的ではなく外部要因で停止
② OOMの確認
journalctl -k
結果:httpd invoked oom-killer
→ メモリ不足確定
③ プロセス確認
ps -ylC httpd --sort:rss
結果:
- 軽いプロセス:7MB前後
- 重いプロセス:40〜48MB
→ 一部の処理でメモリが膨張
④ アクセスログ確認
grep xmlrpc.php access_log
結果:
- POST連打
- 数秒間隔
- 同一IP
→ 攻撃確定
解決手順
① Apacheを起動
systemctl start httpd
② xmlrpc.phpをブロック
<Files "xmlrpc.php">
Require all denied
</Files>
③ Apache再起動
systemctl restart httpd
これでサイトは復旧し、攻撃も遮断できました。
なぜそうなるのか
今回のポイントは3つです。
- xmlrpc.phpは外部からPOSTできる入口
- POSTはPHPを実行するため負荷が高い
- preforkはプロセス単位でメモリを消費する
この3つが重なると👇
少メモリ環境では簡単にOOMに到達します。
まとめ
- ERR_CONNECTION_REFUSEDはアプリではなくサーバー層を疑う
- httpdがkilledならOOMを確認
- xmlrpc.phpは攻撃の入口になりやすい
- 使っていないならブロック推奨
今回のようなケースは、WordPressの問題ではなくインフラの問題
より詳しい判断軸や、同じような障害で詰まらないための思考プロセスについては、noteでまとめています。
・なぜ最初にサーバーを疑うべきなのか
・xmlrpc攻撃の見分け方
・OOMの切り分け手順
気になる方は参考にしてみてください。