WordPress + Cloudflare 環境でサーバー自身のグローバルIPから大量のアクセスを受けている
概要
数か月前から、WordPressに大量のアクセスを受けてCPUとRAMの使用率が100%近くに張り付いています。
DoSられてるのかと思い、Cloudflareの セキュリティー -> 分析 からアクセス元のIPを見てみたら、なぜか自分のサーバーのグローバルIPから大量にリクエストを受けていました。

一体どういうことなんでしょうか?
アクセス元

パスは全て / に対してアクセスされています。
何が原因?

ユーザーエージェントはWordPress。
変なプラグインが悪さしてるのかと思いましたが、全て無効化しても変わりません。
対処療法
仕方がないので、WordPressのユーザーエージェントに対してJSチャレンジ(BOTはじくやつ)を適応するルールを追加します。

GoogleとかTwitterのBOTまで弾かれたら困るのでそれらは除外し、http.user_agent contains “WordPress” で ユーザーエージェントにWordPressが含まれるリクエストに対してチャレンジさせます。ついでに国外からのリクエストにも。
この対処療法で一応は直りましたが、結局何が原因なんでしょうか😢
原因判明 (追記)
適当にサイト内を巡回すると発生するパターンが判明。記事中で自分自身のサイト(tatuiyo.xyz)のURLを埋め込んでいるページにアクセスしたときのみ発生していました!
こんな感じのやつ。
Query Monitor
WordPressにQuery Monitorプラグインを導入し、何のクエリが暴走しているのか割り出します。
Query Monitorを確認するとHTTP API Callsで時間がかかっているようです。中身を見てみると、
https://tatuiyo.xyz/?p=930 cURL error 28: Operation timed out after 5001 milliseconds with 0 bytes received 詳細を見ると
WP_oEmbed->discover()
wp-includes/class-wp-oembed.php:460
WP_oEmbed->get_provider()
wp-includes/class-wp-oembed.php:291
hu_embed_html()
wp-content/themes/hueman/functions/init-wp-core-filters.php:30
apply_filters('embed_oembed_html')
wp-includes/plugin.php:205
WP_Embed->shortcode()
wp-includes/class-wp-embed.php:291
WP_Embed->autoembed_callback()
wp-includes/class-wp-embed.php:466
preg_replace_callback()
wp-includes/class-wp-embed.php:466
WP_Embed->autoembed()
wp-includes/class-wp-embed.php:448
apply_filters('the_content')
wp-includes/plugin.php:205
the_content()
wp-includes/post-template.php:256
load_template('wp-content/themes/hueman/tmpl/single-tmpl.php')
wp-includes/template.php:812
locate_template()
wp-includes/template.php:745
get_template_part('tmpl/single-tmpl')
wp-includes/general-template.php:206
hu_get_template_part()
wp-content/themes/hueman/functions/init-front.php:1741
hu_get_content()
wp-content/themes/hueman/functions/init-front.php:27Huemanテーマの埋め込み機能のバグのよう
ChatGPTに投げる
つまりこういうこと
🧨 問題の根本:自分のURLを自分でoEmbedしようとしていた
🔁 WordPressの標準の流れ:
1.投稿の本文に https://tatuiyo.xyz/?p=930 のような自サイトのURLを貼る
2. WPが oEmbed を試みる
3. テーマの hu_embed_html() が WP_oEmbed->get_provider() を呼び出す
4. WordPress が「よし、そのURL(自分)にアクセスして oEmbed 情報取ろう」として、HTTPリクエスト(curl)で自サイトにアクセス
5. そのアクセスをまた WordPress が受け取り…
6. また oEmbed が発動して…
7. 以下無限ループ!🔥
➡ 結果:Apacheが自分自身に大量アクセスし続けて、CPU100%Bug Fix
自分宛てにHTTPで埋め込みする情報を取得する代わりに、get_post()で直接投稿データを取るように修正します。
(ChatGPT案)
wp-content/themes/hueman/functions/init-wp-core-filters.php を修正
修正前
if ( !function_exists( 'hu_embed_html' ) ) {
function hu_embed_html( $html, $url ) {
if ( !file_exists( ABSPATH . WPINC . '/class-wp-oembed.php' ))
return $html;
require_once( ABSPATH . WPINC . '/class-wp-oembed.php' );
$wp_oembed = _wp_oembed_get_object();
$provider = $wp_oembed -> get_provider( $url, $args = '' );
if ( !$provider || false === $data = $wp_oembed->fetch( $provider, $url, $args ) ) {
return $html;
}
// Check that we have a valid $data object
// for https://wordpress.org/support/topic/error-in-theme-6/
if ( is_object($data) && isset($data->type) ) {
$type = $data->type;
switch( $type ) {
case 'video' :
$html = sprintf('<div class="video-container">%1$s</div>', $html );
break;
}
}
return $html;
}
}修正後
if ( !function_exists( 'hu_embed_html' ) ) {
function hu_embed_html( $html, $url ) {
$home = parse_url(home_url(), PHP_URL_HOST);
$url_host = parse_url($url, PHP_URL_HOST);
// 🔒 自サイトのURLなら、自前で表示内容を組み立て(HTTPアクセスしない)
if ($home === $url_host) {
// クエリパラメータから?p=123の形式で投稿ID取得
parse_str(parse_url($url, PHP_URL_QUERY), $query);
$target_post_id = isset($query['p']) ? intval($query['p']) : 0;
if ($target_post_id) {
$post = get_post($target_post_id);
if ($post) {
$title = esc_html(get_the_title($post));
$permalink = esc_url(get_permalink($post));
return '<div class="self-embed-container">
<strong><a href="' . $permalink . '">' . $title . '</a></strong>
</div>';
}
}
// 該当投稿が見つからなかった場合はURLリンクとして返す
return '<a href="' . esc_url($url) . '">' . esc_html($url) . '</a>';
}
// 🔄 外部oEmbedは今まで通り処理
if ( !file_exists( ABSPATH . WPINC . '/class-wp-oembed.php' ))
return $html;
require_once( ABSPATH . WPINC . '/class-wp-oembed.php' );
$wp_oembed = _wp_oembed_get_object();
$provider = $wp_oembed -> get_provider( $url, $args = '' );
if ( !$provider || false === $data = $wp_oembed->fetch( $provider, $url, $args ) ) {
return $html;
}
if ( is_object($data) && isset($data->type) ) {
$type = $data->type;
switch( $type ) {
case 'video' :
$html = sprintf('<div class="video-container">%1$s</div>', $html );
break;
}
}
return $html;
}
}
自己ループが解消し、埋め込みも機能しました
もうChatGPTいないと何もできない







最近のコメント