コンテンツへ移動

← すべての記事

MMORPGでのボット検知:サーバーサイドの重み蓄積方式

ボットは二値ルールでは捕まえられません。Dofus Touchで重み蓄積方式の検知サービスを構築した手法と、誤検知を避けられる理由を紹介します。

MMORPGでのボット検知:サーバーサイドの重み蓄積方式

Dofus Touchでサーバーサイドのボット検知サービスを構築しました。この問題に取り組むときの誘惑は、ハードルールでコーディングすること:「プレイヤーが2時間ぴったり800msごとにクリックしたらボット」。これは5分間機能します——ボットがジッターを少し加えて再び見えなくなるまでは。そしてその5分間で、たまたま規則的なパターンを持つ実プレイヤーもBANしてしまいます。

実用に耐えるアプローチは重み蓄積です。考え方は次の通り。

原則

各プレイヤーアクションは1つ以上の重み付きカウンターに寄与します。単独のシグナルではBANを引き起こしません。しかし時間の経過とともに複数のシグナルが収束すると、グローバルスコアが閾値を超え、アカウントがフラグ化されます。

これはスコアリングモデル向けフィーチャーエンジニアリングのローテク版です:ドメイン知識を重みとしてエンコードし、分布を観察し、調整する。

どのシグナルか

MMORPGでは、有用なシグナルは決して「単一のメトリクス」ではありません。それらは束です:

  • クリックの時間的規則性(分散が低すぎる = 怪しい)
  • 移動パターン(経路が常にピクセル単位で同一)
  • インベントリのシーケンス(タイミングが完璧なドラッグ&ドロップ)
  • 戦闘サイクルの繰り返し(同じ呪文シーケンス、同じターゲット、ループ)
  • 24/7の接続:人間らしい切断がない(実プレイヤーはトイレに行く)
  • 最適化された農耕ルート(人間は常に寄り道する)

各シグナルには重みがあります。赤に近いもの(1000アクションにわたるミリ秒単位の完璧なタイミング)もあれば、黄色に近いもの(12時間にわたって30分以上の休憩がない)もあります。

アーキテクチャ

サーバー側の実装は意図的にシンプル:

// Java擬似コード
public class BotScoreAccumulator {
    private final Map<PlayerId, ScoreState> scores;

    public void onEvent(PlayerEvent event) {
        ScoreState state = scores.computeIfAbsent(event.playerId(), ScoreState::new);
        for (Detector detector : detectors) {
            double weight = detector.evaluate(event, state.history());
            state.add(detector.id(), weight);
        }
        if (state.totalScore() > FLAG_THRESHOLD) {
            flagForReview(event.playerId(), state.snapshot());
        }
    }
}

いくつかの構造的な選択:

  • スコアリングはメモリ上で行う:定期的に永続化。イベントごとにDBラウンドトリップを発生させずにリアルタイム評価する必要があるため。
  • 時間減衰:重みは時間とともに減少する。3日前の不審な振る舞いは、3分前のそれよりも軽い。そうしないと無限に蓄積し、全員が怪しくなる。
  • フラグ時のスナップショット:閾値到達時に完全な状態(どの検知器が、どの重みで、どの時間ウィンドウで発火したか)を保存し、後から判断を監査できるようにする。

なぜ「本物の」MLを使わなかったか

純粋なMLアプローチ(抽出した特徴に対するランダムフォレスト、またはシーケンスモデル)も検討しました。この特定の文脈では採用しないことに決めました。理由は次の通り。

  • 監査可能性:プレイヤーがBANに異議を唱えたとき、「これらの検知器が、正確にこれらの重みで発火しました」と示せます。ブラックボックスの分類器ではこれがはるかに困難。
  • 迅速な反復:新しいシグナルを追加するのは、数行の検知器コードを追加するだけ。MLモデルの場合、再学習、検証、再デプロイが必要。
  • コスト:GPU基盤ゼロ、MLOpsゼロ。標準的なJavaサービス。
  • 猫とネズミのゲーム:ボットは進化します。ヒューリスティック検知器は数日で調整できますが、MLモデルは完全なサイクルを要します。

新種のボットをゼロショットで複雑な振る舞いを分類する必要がある場合は、MLが正解だったでしょう。よく知られたMMORPGの農耕ボット検知では、重み付きヒューリスティックの方が反復が速く、運用上も擁護しやすい選択でした。

誤検知:本当の試金石

アンチボットシステムの本当の試験は「ボットを何件BANしたか」ではありません。「実プレイヤーを何件誤BANしたか」です。人気プレイヤーへの誤BANが1件あるだけで、コミュニティマネージャーの週末が燃えます。

2つの安全策:

  1. フラグとBANの間の「レビュー」段階。フラグ閾値の到達は調査(GMまたは第三者サービスによる)を引き起こすのであって、自動BANではない。自動BAN閾値ははるかに高く設定。
  2. フィードバックループ:手動BANまたはBAN解除はすべて分析にフィードバックされ、重みの調整に使われる。

学んだこと

  • この種の問題には、二値ルールよりも重み付きヒューリスティックの方が良い。
  • 時間減衰を伴う蓄積はドリフトを防ぐ。
  • 監査可能性は「あれば嬉しい」ではなく「機能」である。プレイヤーが異議を唱えたとき、説明できなければならない。
  • MLはその後で——ヒューリスティックが取りこぼすケースに対して。

Dofus Touchでは、このシステムが非人間アカウントの数を削減しました。アルゴリズム上の大革命ではなく、ドメインモデリングの規律と誤検知に対する厳格さによって。