ある日、リクエスト数が10倍に膨れ上がった
2026年3月22日、日曜日の朝。kyotanishokai.co.jpのCloudflareダッシュボードを開いた瞬間、目を疑った。前日まで1日あたり6,000〜8,000程度で推移していたユニークビジター数が異常な伸びを見せ、リクエスト数に至っては1,262,000件/日という数字を叩き出していた。通常の約10倍である。
京谷商会は大阪府南河内郡太子町に拠点を置く小規模事業者だが、kyotanishokai.co.jp配下に18のナレッジポータルを運営している。SEO、セキュリティ、AI活用、Web制作など、それぞれが専門分野に特化したサブドメイン型の構成で、すべてCloudflare Workers/Pages上でホスティングしている。この18サブドメインすべてが、同時に異常なアクセスを受けていた。
最初に確認したのはCloudflareのセキュリティイベント画面だったが、ここに表示されていた脅威検出数はわずか4件。126万リクエストに対して4件。つまりCloudflareのデフォルト設定では、この大量アクセスの99.9997%を「正常なトラフィック」として素通りさせていたことになる。
PV(ページビュー)は413,000件に達しており、これは当社の全ポータルのコンテンツがまるごとクロールされている規模感だった。しかしGoogle Analyticsの数値は平常通り。ここからブラウザのJavaScriptを実行しない、つまり人間ではないアクセス——ボットによる大規模スクレイピングだと確信した。
Cloudflare Radarの2026年第1四半期データによると、インターネットトラフィック全体の約50%がボットによるものとされている。そのうち約3割が悪性ボットであり、中小企業サイトも例外ではない。当社の事例はまさにこの統計を体感する出来事だった。
攻撃の正体を特定する — Cloudflare GraphQL Analytics APIの活用
敵を知らなければ対処はできない。ダッシュボードの概要画面だけでは攻撃の全体像が見えないため、Cloudflare GraphQL Analytics APIを使って詳細データを引き出した。
まずリクエストの国別分布を確認した。結果は圧倒的で、米国(US)から1,240,000件、フランス(FR)とイギリス(GB)が数千件ずつという構成だった。当社サイトは日本語コンテンツしか掲載していないため、米国から124万リクエストが飛んでくる正当な理由は存在しない。
次にUser-Agentの分布を調べた。攻撃者のリクエストには大きく3つのパターンがあった。第一に、User-Agentが完全に空のリクエスト。これは最も基本的なスクレイピングツールの特徴だ。第二に、sqlmap、nikto、nmap、zgrab、nucleiといったセキュリティスキャンツールの名前をそのままUser-Agentに入れているリクエスト。OWASP Automated Threatsが分類する「OAT-004 Fingerprinting」や「OAT-018 Credential Stuffing」に該当する脆弱性探索の自動化が行われていた。第三に、一見正規のブラウザを装ったUser-Agentだが、アクセスパターンが人間離れしたもの。1秒間に数十リクエストを同一IPから送信するような挙動である。
リクエストパスの分析では、WordPressの脆弱性を狙ったプロービングが大量に見つかった。/wp-content/、/wp-admin/、/wp-login.phpといったWordPress固有のパスへのアクセスが数万件単位で記録されていた。当社サイトはCloudflare Workers/Pages上で動作しておりWordPressは一切使っていないため、これらのアクセスはすべて無駄打ちではある。しかし、サーバーリソースを消費し、Cloudflareの無料プランにおけるリクエスト数上限を圧迫するという点で実害がある。WordPress環境を運用している場合のプラグイン脆弱性対策については、WordPressプラグイン脆弱性管理の実務で詳しく解説している。
さらに/.env、/.git/config、/phpmyadmin/へのアクセスも多数検出された。環境変数ファイルやGitの設定情報を抜き取ろうとする典型的な偵察行為だ。また、200文字を超える異常に長いパスを使ったリクエストも記録されており、バッファオーバーフローやパストラバーサルを狙った攻撃の可能性があった。
Cloudflare無料プランで組む多層防御の設計思想
攻撃の全体像を把握した上で、3月25日に対策を実施した。ここで重要な制約条件がある。当社が利用しているのはCloudflareの無料プランであり、使えるカスタムWAFルールは最大5件という制限がある。Enterprise版なら数百のルールを組めるが、5件で同等の防御力を出さなければならない。
設計にあたって意識したのは次の原則だ。
正規クローラーを絶対にブロックしてはならない。GooglebotやBingbotを誤って遮断すれば、SEOに致命的なダメージが出る。18ポータルの検索順位が落ちれば事業への影響は甚大だ。したがって、最初のルールは「許可リスト」として正規クローラーを明示的にスキップさせる構成にした。
次に、明らかに悪意のあるリクエストは即座にブロックする。空User-Agentや攻撃ツールのシグネチャは弁明の余地がないため、ここでは判定ミスを恐れずにBlockアクションを適用した。
グレーゾーンのリクエストにはManaged Challengeで対応する。人間であれば数秒で通過できるが、ボットには突破が難しいチャレンジを挟むことで、偽陽性のリスクを最小限に抑えつつ防御する。
そしてWordPress関連パスや異常パスへのアクセスはBlockで処理する。当社にWordPressは存在しないため、こちらも誤検知の心配はゼロだ。
この5件のルールを「許可→遮断→検査→遮断→遮断」の順序で評価させることで、正規トラフィックは最初のルールで即座に通過し、攻撃トラフィックは2番目以降のルールで段階的に除去される多層構造を実現した。なお、こうした多層防御の考え方を含む包括的なセキュリティ対策については、Webサイトのセキュリティ対策チェックリスト2026年版も参照してほしい。
カスタムWAFルール5件の具体的な設定内容
実際に設定した5件のルールを、評価順に記載する。
ルール1: 正規クローラーのスキップ。条件はcf.client.botがtrueであること。アクションはSkip(すべてのセキュリティルールをスキップ)。CloudflareはVerified BotsとしてGooglebotやBingbotなど主要な検索エンジンクローラーを識別しており、cf.client.botフラグでこれを判定できる。このルールを最上位に置くことで、正規クローラーが後続のルールでブロックされることを防ぐ。
ルール2: 空User-Agentと攻撃ツールのブロック。条件は、User-Agentヘッダーが空であること、またはUser-Agentにsqlmap、nikto、nmap、zgrab、nucleiのいずれかを含むこと。アクションはBlock。正規のブラウザやクローラーがUser-Agentを空にすることはまずない。また、上記の文字列はいずれもオープンソースの脆弱性スキャンツールの名称であり、これらをUser-Agentに含むリクエストが正当なアクセスである可能性は極めて低い。
ルール3: 脅威スコアに基づくManaged Challenge。条件はcf.threat_scoreが14より大きいこと。アクションはManaged Challenge。Cloudflareは各リクエストに0〜100の脅威スコアを付与しており、数値が高いほど悪意がある可能性が高い。閾値を14に設定したのは、Cloudflareの推奨値(Low設定相当)を参考にしつつ、実データで正規ユーザーへの影響を検証した結果だ。
ルール4: WordPress・偵察パスのブロック。条件は、URIパスが/wp-content/、/wp-admin/、/wp-login.php、/wp-includes/、/.env、/.git、/phpmyadminのいずれかで始まること。アクションはBlock。当社サイトにWordPressは存在しないため、これらのパスへのアクセスは100%不正なプロービングだ。
ルール5: 異常に長いパスのブロック。条件は、URIパスの長さが200文字を超えること。アクションはBlock。当社の全ポータルにおいて、正規のURLパスが200文字を超えることはない。
Bot Fight Modeの有効化と効果計測
カスタムWAFルールに加えて、CloudflareのBot Fight Modeを有効化した。これは無料プランで利用できる機能で、有効にするとCloudflareが自動的にボットと判定したリクエストに対してJavaScriptチャレンジを発行する。
Bot Fight Modeの仕組みは、ブラウザにJavaScriptの計算処理を要求し、その応答を検証するというものだ。人間が操作する通常のブラウザであればバックグラウンドで自動的に処理が完了するが、単純なHTTPクライアントやスクレイピングツールはJavaScriptを実行できないため、チャレンジを突破できずにアクセスが遮断される。
同時に、CloudflareのSecurity Level設定を「Low」に調整した。これは一見矛盾するように思えるかもしれない。攻撃を受けているのに防御レベルを下げるのかと。しかし実際の意図は異なる。Bot Fight ModeがJavaScriptチャレンジで高精度なボット判定を行ってくれるため、Security Levelを過度に高くすると正規ユーザーにまで不要なチャレンジが表示されてしまう。「Low」に設定することで、Bot Fight Modeの判定を主軸にしつつ、人間のユーザーには快適なアクセス体験を維持するバランスを取った。
なお、WebサイトのHTTPレスポンスヘッダーを適切に設定することも、ボット対策とは別の観点でセキュリティ強化に寄与する。Content-Security-PolicyやX-Frame-Optionsなど、HTTPセキュリティヘッダーの設定方法については別記事で詳しく解説している。
対策後の数値検証 — PV 99%減の内訳を読み解く
対策実施前後の数値を比較する。
ページビューは413,000件/日から2,800件/日に減少した。減少率は99.3%である。この劇的な数字は、ボットがコンテンツを取得できなくなったことを意味する。WAFルールでブロックされたリクエストはページビューとしてカウントされず、Bot Fight ModeのJavaScriptチャレンジを突破できなかったリクエストも同様だ。
一方でリクエスト数は1,014,000件/日から742,000件/日への減少にとどまっている。減少率は約27%。PVが99%減っているのにリクエスト数が27%しか減っていないのはなぜか。これはボットが依然としてリクエスト自体は送り続けているが、WAFルールでBlockされるか、Bot Fight ModeのJavaScriptチャレンジで弾かれているためだ。
脅威検出率は93%に達した。対策前はわずか4件しか検出できなかったCloudflareのセキュリティ機能が、カスタムルールとBot Fight Modeの組み合わせによって攻撃トラフィックの93%を脅威として識別・処理できるようになった。
正規トラフィックの指標として、2xx(成功)レスポンスの推移を確認した。対策前後で2xxレスポンスは1時間あたり200〜400件の範囲で安定しており、有意な減少は見られなかった。つまり、人間のユーザーによるアクセスは対策の影響をほぼ受けていない。
正規トラフィックへの影響を最小化するための工夫
ボット対策で最も難しいのは、攻撃を遮断することではない。正規のユーザーやクローラーへの影響を最小化しながら攻撃を遮断することだ。今回の対策では、いくつかの工夫でこのバランスを追求した。
まず、ルール1でcf.client.botによる正規クローラーの明示的なスキップを最上位に配置した設計がある。Cloudflareのルール評価は上から順に行われ、最初にマッチしたルールが適用される。正規クローラーは最初のルールでスキップされるため、後続のルールがどれだけ攻撃的な設定であっても影響を受けない。これにより検索エンジンのインデックスへの悪影響をゼロに抑えた。
次に、ルール3の脅威スコア閾値を14に設定した判断がある。Cloudflareの脅威スコアは0(安全)から100(危険)のスケールだが、閾値を低くしすぎると正規ユーザーにチャレンジが表示される頻度が上がる。14という値は「中程度以上の脅威が疑われるリクエスト」にのみチャレンジを課す水準であり、一般的なブラウザからの通常アクセスがこのスコアに達することは稀だ。
Security Levelを「Low」に設定した判断も重要だ。Cloudflareのデフォルト設定やドキュメントでは攻撃時に「High」や「I''m Under Attack」モードへの切り替えを推奨しているが、これらは正規ユーザーへの影響が大きい。今回はBot Fight Modeのインテリジェントな判定に防御の主軸を委ね、Security Levelは控えめな設定にとどめた。
対策後の継続監視と攻撃手法の進化
対策を導入して終わりではない。ボット攻撃の手法は日々進化しており、継続的な監視と調整が不可欠だ。
当社では対策導入後、以下の3つの指標を週次で確認している。
1. WAFルール別のブロック数推移: 特定のルールだけブロック数が急増していれば、攻撃パターンが変化した兆候だ。Cloudflareダッシュボードのセキュリティイベント画面で、ルールごとのヒット数を時系列で確認できる。
2. Bot Fight Modeのチャレンジ突破率: 通常、単純なHTTPクライアントはJavaScriptチャレンジを突破できない。しかし2026年に入り、Playwright・Puppeteerなどのヘッドレスブラウザを使ってJavaScriptチャレンジを自動突破するボットが増加している。チャレンジ突破率が上昇傾向にある場合は、追加のWAFルールやRate Limitingの導入を検討する必要がある。
3. 2xxレスポンス率の安定性: 正規ユーザーのアクセスが対策の影響を受けていないかの確認。2xx率が急落した場合、正規トラフィックを誤ブロックしている可能性がある。
Cloudflareの無料プランでも、5件のWAFルールとBot Fight Modeの組み合わせで、126万リクエスト規模のボット攻撃を実質的に無力化できる。ただし、これは万能の対策ではない。攻撃者がJavaScript実行環境を備えたヘッドレスブラウザに切り替えたり、住居用IPアドレスを経由するレジデンシャルプロキシを使用した場合、Bot Fight Modeの効果は低下する。今回の対策はあくまで「現在の攻撃パターン」に対する最適解であり、攻撃手法の変化に応じてルールを継続的に見直していく必要がある。
セキュリティに完成はない。しかし、Cloudflareの無料プランが提供する機能を正しく理解し、適切に組み合わせれば、大規模なボット攻撃に対して十分な防御力を発揮できることを、今回のインシデントは証明している。