世界を動かす技術を、日本語で。

ボットに餌を与える

2025年10月26日原文(maurycyz.com)

概要

  • サーバーのトラフィックの大半を占める AIスクレイパーボット の問題点
  • 従来の 対策(IPブロックやレート制限) が効かない現状
  • 静的ファイル提供 のコストや帯域幅の課題
  • 動的にナンセンスなデータ を返すことでコストを抑えた対策
  • 結果的に ボット対策の新しいアプローチ として有効性を示唆

AIスクレイパーボットとの闘い

  • サーバートラフィックの 99%がAIスクレイパーボット によるもの
  • これらのボットは 従来のインデックス用クローラー ではなく、LLM(大規模言語モデル)学習用データ収集が目的
  • robots.txt無視User-Agent偽装IPアドレス切替 による執拗なアクセス
  • 一日中、 毎秒複数リクエスト を送信する過剰な負荷
  • サイトを開放しても 静的ファイル提供コスト帯域幅消費 が無視できない
    • 例:平均ファイルサイズ100kB、毎秒4リクエストで月1TB消費
  • ブロックリストやレート制限が IP切替戦術 の前に無力化
    • 1リクエストごとに新しいIPを使う例も観測

従来の対策とその限界

  • ペイウォールログイン必須CAPTCHAJavaScriptチャレンジ などの壁
    • 一般ユーザーの利便性を大きく損なう
    • JavaScript未対応環境や遅延の増加問題
  • Gzip爆弾 による対策の無効化
    • 圧縮率の限界(100GB展開で100MB配信必要)
    • ボット側が容易に対処し再訪問
  • 404レスポンス 等の“存在しないふり”戦略
    • ボットはリンクが存在する限り より攻撃的にアクセス
    • 結果としてリクエスト増加

新しいアプローチ:ナンセンスデータの動的生成

  • Markov連鎖によるナンセンス生成器 を導入
    • 1リクエストあたりCPU60マイクロ秒程度で動作
    • ディスクIO不要メモリ消費1.2MB程度 の低コスト
  • 動的生成は CPU・RAM主体 で、従来の“遅い”イメージは誤解
    • データベースや複雑なJavaScriptを経由しない設計
  • ブラックリスト管理不要
    • ボットが勝手に引っかかり、サーバー資源をほぼ消費しない
  • “ゴミを食わせる” ことで、実質的な被害を最小化

まとめ:AI時代のボット対策指針

  • 従来手法の限界 を認識
    • IPブロックやレート制限はもはや無効
  • ユーザー体験を損なわず、サーバーコストを抑えるための新戦略
    • ボットには意味のないデータを与え、 資源の消耗を抑制
  • AIスクレイパーの性質 を逆手に取った対策が今後有効
  • 技術的な工夫による 持続可能なWeb運営 の重要性

参考: Trap Bots Project by Maurycy

Hackerたちの意見

このフォローアップ投稿には「マルコフバブラー」の詳細が載ってるよ: https://maurycyz.com/projects/trap_bots/

とてもエレガントで、意外とパフォーマンスもいいね。LLMの連中がこれをスクレイピングから排除するのに苦労することを願ってるよ。

ありがとう、それもトップテキストに入れておくね。

babble.cがgcc 14でコンパイルできないのは興味深いね: babble.c: 関数 ‘main’ 内: babble.c:651:40: エラー: ‘pthread_detach’ の引数1を渡すと、キャストなしでポインタから整数に変換される [-Wint-conversion] 651 | pthread_detach(&thread); | ^~~~~~~ | | | pthread_t * {aka long unsigned int *} babble.c:77からインクルードされたファイル: /usr/include/pthread.h:269:38: 注意: 期待されるのは ‘pthread_t’ {aka ‘long unsigned int’} だけど、引数は ‘pthread_t *’ {aka ‘long unsigned int *’} 269 | extern int pthread_detach (pthread_t __th) __THROW; 著者はデフォルトでその警告を表示しないコンパイラを使っているか、デフォルトでその警告でエラーが出ないコンパイラを使っているんだろうね。でも、プログラムがクラッシュしないのは驚きだよ(少なくとも、最終的にメモリが足りなくならないのも驚きだね。libcが実際にそのスレッドをデタッチできないだろうし、pthread_join()が呼ばれることもないから)。このバイナリはCで手動のテキスト解析や文字列操作をたくさんやってるから(基本的なHTTPサーバーを実装することも含めて)、少なくとも特権のないユーザーとして実行することをおすすめするよ(著者も提供されたsystemdユニットファイルで暗に推奨してるし)、コンテナ内で実行するのがいいかもね(絶対に安全とは言えないけど、何もしないよりはマシかも)。このプログラムはsprintf()のような安全でないC関数も使ってる。一つのインスタンスをざっと見た感じでは、その使い方は確かに安全そうだけど、そういうのはプログラム全体の安全性に対して赤信号が点灯するよね。リクエストをすごく早く処理するけど、各リクエストを処理するために作成する同時スレッドの数に制限がないみたいだから、注意が必要だね。

まだ、ボットが俺の(ゼロトラフィックの)ウェブサイトの全リンクを守ってる基本認証を突破するのを見たことがないんだ。もちろん、リンクをクリックしたユーザーは同じログインダイアログで止められる(クレデンシャルはホームページに表示してる)。解決策は秘密を公開することだね。すべてのウェブサイトが同じユーザー名/パスワードを実装できる:ユーザー:nobots パス:nobots ボット作成者は、クレデンシャルを知っていればこれを克服できるのかな?

ボット作成者は、クレデンシャルを知っていればこれを克服できるのかな? うん、ただのHTTPリクエストじゃなくて、認証付きのHTTPリクエストをすればいいだけ。ほんとに簡単だよ。今「できない」理由は、彼らが「正しいクレデンシャルのある基本認証の裏にある公開コンテンツ」に出くわしてないからだと思う。だからその動作が追加されてないんだ。でも、基本認証を使うためにはhttp://example.comの代わりにhttp://username:password@example.comを読み込むだけだから、めっちゃ簡単だよ :)

ちょっとついていけるかわからないけど、誰でも知ってるクレデンシャルがボットを止める理由は何?

賢い解決策だけど、メインストリームになったり、ちょっとでも人気が出たりしない限りは機能するだろうね。

なんでマルコフテキストをサーバーサイドで作るの?ボットがJavaScriptを実行してるなら、クライアントに生成させればいいじゃん。

  1. ボットは基本的に無限のメモリとCPUを持ってる。これがスクレイピングセットアップで一番安い部分だよ。 2. マルコフチェーンジェネレーターのデータをクライアントに送る必要があるし、コードも一緒にね。これ、送るレスポンスよりも大きくなると思うよ。(ボットにJavaScriptをキャッシュさせるのは難しいし) 3. 著者が言ったように、各リクエストはマイクロ秒単位のCPUを使って、ちょうど1メガバイトのRAMを使う。これ、誰にとっても負担じゃないよ。

ありがとう、今はゴミを提供してるよ :) 参考までに、フランケンシュタイン、アリス・イン・ワンダーランド、モビー・ディックをソースに選んだんだけど、ちょっと大きすぎるかも。読み込みに時間がかかるからね。でも、ちゃんと動いてるよ。スレッド処理のbabble.cにバグがあるみたい?gccの提案通りにpthread_detach(&thread)をpthread_detach(thread)に変更して「修正」したんだけど…多分何か壊しちゃったかも。でも、今はコンパイルも実行もできてる :)

ごめん、直したよ。(そうそう、gccが提案した修正が正しいやつだよ。)

Hacker Newsで議論の続きを見る