scenario-roblox-networking について
Roblox Studio向けのネットワークとセキュリティのスキルです。リモート呼び出しの監査やクライアント入力の検証を行い、敵対的なテストで防御を確かめます。
主な機能
- 01リモート呼び出しの監査と検証
- 02レート制限と引数チェック
- 03命中と移動の検証
- 04インタラクティブ要素の所有権確認
- 05エクスプロイトのファジングと遅延テスト
活用シーン
- 01Robloxのリモート呼び出しのレビュー
- 02スパムや偽造引数への防御テスト
- 03遅延環境での戦闘命中判定の検証
- 04クライアント所有オブジェクトによる結果決定の防止
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ scenario-labs/ skills --skill scenario-roblox-networkingインストール後、Claude Code で/scenario-roblox-networkingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/critique.mdexpert-notes.mdgui-paths.mdprocedures.mdsources.mdscripts/rbx_net.pyscripts/agentkit/networking/Exploit.luauGuard.luauHitCheck.luaulune_net_audit.luauMoveGuard.luauNet.luauNetAudit.luauRateLimit.luauSuspicion.luau詳細
Roblox のネットワークとセキュリティ
対象:scenario-roblox-expert ツールキットを通じて操作する、macOS 上の Roblox Studio(2026 年 10 月ビルド)。
ここでいうエキスパートレベルとは、クライアントから実行できるすべてのアクションを攻撃者の入力として扱うことです。サーバーが状態を所有し、呼び出しごとに決められた順序でチェックし、プレイテストクライアントから悪意のある引数を送信して、その対策を実証します。検出は検証を補完し、目に見える結果はさまざまなシグナルを受けて後から現れます。
ここで名前が挙がっている同系統のスキルが利用可能なスキルにない場合は、ユーザーにインストールを依頼してください(npx skills add scenario-labs/skills --skill <name>)。無人で作業する場合は、ツールのスキーマを基に進め、不足している点を明示してください。
必須の事前知識: scenario-roblox-expert(チャンネル、レビューの反復、ツールキット、現行 Roblox の落とし穴)。
基本方針(エキスパートとして追加する点)
- Remote は意図を運び、結果は運びません。 クライアントがアイテムを指定し、サーバーが価格を決定します。武器が報告するのは発射元と着弾地点であり、被害者やダメージではありません(Creator Docs、クライアントとサーバーの境界;GnomeCode)。
- 固定順序でチェックします。まずレート、次に引数、最後にコンテキストです。 ドキュメントではコンテキスト、型、値、レートの順に列挙されていますが、レート制限を最初に行うほうが低コストです[追加]。NaN は
typeof(v) == "number"を通過し、すべての比較に失敗するため、math.isfiniteを使用してください(Creator Docs;Suphi Kaner)。ライブ環境で、範囲チェックしか行わないハンドラーに NaN と無限大のペイロードを送信したところ、IntValue の残高が -9223372036854775808 に設定されました。 - Instance 引数は申告です。
typeofとIsDescendantOf(expectedFolder)をチェックしてください。テーブルは Instance を装うことができ、クライアントは参照を保持している破棄済みのピックアップを再送できます(Creator Docs;Suphi Kaner)。 - クライアントから実行できるすべての操作箇所は Remote です。 ProximityPrompt は
Triggeredのときだけ距離をチェックし、Enabledは無視します。ClickDetector にはサーバー側のチェックがありません。Touchedはクライアント側の物理演算を報告します(Creator Docs;Suphi Kaner)。 - 移動:新しい対戦ゲームでは Server Authority、既存のカジュアルなゲームではサーバー側の MoveGuard を使用します。 判断基準はジャンルと、固定シミュレーション、InputActions、ストリーミングを採用できるかどうかです(Creator Docs;Jason Knight、Roblox)。Server Authority でも、ESP、エイムボット、カメラの悪用は防げません(ev1)。
- 攻撃者が見た状態に基づいてヒットを検証します。 Roblox に組み込みのラグ補正はありません(ev1)。サーバーが記録した位置を
[now - min(ping + 0.1, 0.4), now]の範囲で巻き戻す[追加]か、約 10 度のコーンを使用します(ev1)。遮蔽物の判定には静的なジオメトリのみを使用します(Creator Docs)。 - 処罰は段階的に強め、時間を置いて実行します。 減衰する疑わしさのスコアを保持し、処罰には異なる理由を 2 つ要求し、目に見える対応はランダムに 20~90 秒遅らせます[数値を追加]。ハニーポット Remote と方向ハニーポットは、信頼度の高いシグナルです(Creator Docs、サーバー側の検出)。移動では、ラグによる誤検知を避けるため、キックではなくラバーバンドで元に戻します(GnomeCode)。
- UnreliableRemoteEvent は、1,000 バイト未満の頻繁な装飾データにのみ使用します。 上限は 1,000 バイトです(Creator Docs)。2025 年の Roblox Learn 動画にある 900 という数値は古く、ライブ環境では 980 バイトのランダムなバッファが届いた一方、1,000 バイトのものは破棄されました。どちらの Remote タイプにも同一の検証が必要です。
まず確認すること
Workspace.AuthorityMode:Automatic はクライアント所有のキャラクターを意味します(MoveGuard が適用されます)。Server はエンジンがキャラクターをシミュレートすることを意味します。rbx_net.audit_place(place)は、オフラインで6つすべての設定を読み取ります。- リスクレベル:競技用かカジュアル用か、公開運用中かプロトタイプか。プロトタイプではハニーポットやランキング表は後回しにできますが、検証は後回しにできません。
- Remote の一覧:名前、方向、頻度、ペイロードサイズ、および各ハンドラーが書き込むサーバー値。
- インタラクティブな対象:プロンプト、ClickDetectors、DragDetectors、
Touchedによる取得処理、およびそれらの親がアンカーされていないかどうか。 - 適用ポリシー:キック、
Players:BanAsync、または緩和策のみのいずれか。異議申し立てへの対応担当者(Net.reset)。 - 回答がない場合のデフォルト:すべての Remote で
Net.bindを使用し、ハニーポットを1つ設置し、サーバーからクライアントへの Remote にはNet.serverOnlyを適用し、テスト中の適用はドライランにします。
手順
各段階はツールキットを使って実行してください。コード全体とテスト結果は
procedures.md にあります。ステータス:Studio 0.743 で実施した24件のライブテストに合格しています(アリーナでの再実行および Server Authority の place を2026-10-19に実施)。NetKit(Guard、RateLimit、Suspicion、Net、HitCheck、MoveGuard)は、1つのサーバーフォルダー内に ModuleScript として配置してください。rbx_net.kit_tree(project_dir) はテスト用 place の Rojo フラグメントを生成します。ユーザーのリポジトリでは、rbx_net.vendor_kit(repo, dest) がモジュールをコピーし、リポジトリ内のパスを返します。
- 監査。 目標:すべてのリモート、ハンドラー、インタラクティブなインスタンスと、その調査結果の一覧を作成します。方法:
Lune でオフライン実行する
rbx_net.audit_place(place)の後、 Edit でrbx_net.run(studio, "return NetAudit.run(game, Audit)", kit=["NetAudit"], lead_kit=["Audit"])を実行します。GATE:エラーがゼロであること。すべての警告が修正済み、または正当化されていること。ライブ環境の集計がオフラインの集計と一致すること。 - 検証と制限。 目標:不正な引数や過剰な頻度でハンドラーが実行されないようにします。方法:
クライアントからサーバーへのすべてのリモートに
Net.bind(remote, {args = {Guard...}, limit = {capacity, perSecond}, handler = fn})を使用します。サーバー側のクロックで冪等なハンドラーを使用します。GATE:監査でhandler-unvalidated、nan-unsafe、trusted-value、no-rate-limitの検出結果がないこと。 - ヒット判定。 目標:攻撃判定を履歴と照合します。方法:ターゲットごとに 1 秒分の
HitCheck.Historyを用意し、毎 Heartbeat で更新します。静的な壁にはExcludeInstancesまたはIncludeInstancesを指定してHitCheck.meleeとHitCheck.rangedを使用します。GATE:射程外、偽装した発射元、壁越し、位置ずれのショットが拒否され、有効なショットが命中すること。 - 移動。 目標:誤検知を避けながら、速度ハックやテレポートハックを無効化します。方法:Server Authority(Rojo が設定を書き込みます。ステージ P11)、または、サーバー側でテレポートするたびに
MoveGuard.grace(player, s)を呼び出してからMoveGuard.startを使用します。enforce = falseはログ記録のみを行い、その後、キャラクターがいる位置を基準に測定します。GATE:正規の歩行ではフラグが 0 件であること。クライアントのテレポートとローカルの WalkSpeed 変更がラバーバンドされること(ライブ環境:WalkSpeed 80 を 2.5 秒間設定しても、サーバー側の移動距離は 12.6 studs)。Server Authority のライブ環境では、W を 2 秒間押すとサーバーのキャラクターは 32.4 studs 移動し、クライアントのテレポートでは 0 studs、ローカルの WalkSpeed を 80 に設定してから W を押すと 32.0 studs 移動しました。 - 所有権とサーフェス。 目標:クライアント所有のパーツが結果を左右しないようにします。方法:
アンカーされていないピックアップ、NPC のルートパーツ、プロンプトの親に
SetNetworkOwner(nil)を設定します。Net.promptで距離、状態、頻度を再確認します。MouseClickに距離チェックを追加します。TouchedピックアップにはNet.touchを使用します(タッチしたプレイヤー、CanTouch、距離、MoveGuard の到達可能範囲、共有リミッター)。GATE:クライアントが CFrame を書き換えても、サーバー側では何も移動しないこと。 - クライアントからのエクスプロイトテスト。 目標:意図ではなく、証拠を確認します。方法:
Playtestでrbx_net.fuzz(pt, path, gap=...)、同一フレーム内のスパム、ハニーポットの発火を行い、その後、Server データモデルでrbx_net.net_log(pt)を実行します。意図的に脆弱にしたリモートをネガティブコントロールとして含めます。GATE:残高と体力に変化がないこと。ok_<Remote>が有効なケースの件数と一致すること。サーバースクリプトエラーがないこと。ネガティブコントロールでは報酬が発生すること。Touchedピックアップにはリモートがありません。クライアントをそのパーツにテレポートさせるexploit_caseを使い、その後、Net.touchのパーツと通常のTouchedパーツを並べて比較します(P6)。 - 検出と対処。 目標:確度の高いシグナルを基に、遅延を設けて対処します。方法:
Net.init({enforce = ..., enforceDelay = {20, 90}})、Net.honeypot、Net.serverOnlyを使用します。GATE:ハニーポットが 1 回発火すると、スケジュールされた遅延の後にenforceに到達すること。フラッドだけではrestrictのしきい値を下回ること。 - レイテンシ。 目標:実際の ping でも正規のプレイが成立するようにします。方法:Play の前に Edit で
rbx_net.set_latency(studio, 100, 100)を設定し、動くターゲットに対して直前に攻撃を行います。GATE:巻き戻しによるヒット率が 0.8 以上であること。ライブ環境で ping が 202 ms の場合、巻き戻しありでは 13 回中 13 回、巻き戻しなしでは 13 回中 0 回でした(3 回実施)。射程に余裕を加えた範囲内で、直前に攻撃を開始します。余裕が 0.2 秒残っている場合、巻き戻しなしの成功率は実施ごとに 31~92 パーセントの範囲で変動しました。 - 帯域幅。 目標:変更時のみ送信し、通信量を抑えます。方法:信頼性のない配信を選ぶ前に
rbx_net.payload_probeを実行します。bufferでパックし、ストリームにはシーケンス番号を付けます。GATE:測定したペイロードが上限未満であること。ストリームで受け付けられた件数が送信件数と一致すること。
数値
| 値 | 対象 | 出典 |
|---|---|---|
| 1,000 バイト | 圧縮後の UnreliableRemoteEvent ペイロード。バッファー 1 個だけなら 996 バイト | ドキュメント。実測:ランダムな 980 バイトは届き、1,000 バイトは「4 バイト超過」となった |
| 約 500 件/秒 | クライアントごとのクライアントからサーバーへのリクエスト数(リモートの種類ごと) | RemoteEvent のリファレンス。Studio のプレイテストでは確認できず(実測:0.5 秒以内に 1,000 件到着) |
| バースト 5、2 秒ごとに 1 件 | ドキュメントのトークンバケットの例 TokenBucket.new(5, 10) | ドキュメント |
| 1 秒間に 50 件の呼び出しを破棄 | ウィンドウごとに 1 回発生するフラッド検出のしきい値 | [追加] |
| WalkSpeed + 5 studs/s | MoveGuard が許容する XZ 方向の速度。dt の上限は 0.01 秒 | Suphi Kaner |
| 6 studs、リーク速度 0.5/s | MoveGuard のバーストバケット | [追加] |
| 補間 0.1 s、上限 0.4 s | 巻き戻しウィンドウ [now - min(ping + 0.1, 0.4), now] | [追加] |
| 約 10 度 | ヒットの妥当性を判定する円錐 | ev1 |
| 1、3、6、10 | 疑わしさのレベル。ログ記録、軽減、制限、強制適用。半減期は 120 s | [追加] |
| 20〜90 s | 表示される制裁が実行されるまでのランダムな遅延 | [追加] |
| 64、50 文字 | 予測対象のインスタンスごとに複製される属性。名前と文字列の長さ | ドキュメント |
| 0.5 パーセント | スクリプトで設定した最大パケットロス率(5 は 0.5 として読み取られる) | 実測 |
| 50 KB/s | Roblox のクライアントごとの送受信目標値(Stewiepfing は 25 を目指す) | Stewiepfing |
品質ゲート
測定可能な項目:
- 監査:エラーがゼロであること。警告はすべて解決するか、理由を記録します。
- ファズ:敵対的なケースはすべて
args_<Remote>またはrate_<Remote>に到達し、残高、ヘルス、拾得物が変化しないこと。 - スパム:同一フレームで報酬を1,000回付与しても1回だけ付与され、購入額がバケットを超えないこと。
- ヒット、移動、所有権、プロンプト:判定カウンターがテストケース(手順 P4~P6)と一致すること。
- ファズ実行中のコンソール:ハンドラーに起因する
ServerScriptService.<script>:<line>エラーがないこと。 - レイテンシ:片道100 msでのヒット率がベースラインの0.2以内であること。
- 型:両方の Luau ソルバーでエラーがゼロであること。
rojo sourcemap --include-non-scriptsでソースマップを生成し、--flag:LuauSolverV2=trueの有無それぞれでluau-lsp analyzeを実行します(scenario-roblox-tooling ゲート)。
視覚的な項目:
- プレイ中にクライアントをキャプチャし、
rbx_review.image_checksのフラグがないこと。 - Server Authority の場合、シミュレートしたレイテンシ下のビジュアライザー(GUI のみ、 gui-paths.md)。
完了とする前に、critique.md を使って結果を評価してください。
よくある間違い
| 間違い | 症状 | 修正 |
|---|---|---|
math.isfinite を使わない範囲チェック | 残高が NaN または INT64_MIN になる | Guard.num、Guard.int、Guard.vec3 |
| クライアントが価格、ダメージ、数量を送信する | アイテムが無料になる、資金が無限になる | クライアントはアイテム名を指定し、サーバーが検索する |
| 拾得物のガードをデバウンスだけにする | リプレイで拾得物が重複する | Guard.inst(folder) を使い、付与時に破棄する |
| クライアント側だけでレート制限する | Remote のスパムが引き続き到達する | UserId ごとのサーバーバケットを設け、PlayerRemoving 時にクリアする |
| 移動フラグ1つでキックする | ラグのあるプレイヤーがキックされる | ラバーバンド処理、スコア、理由2つ、遅延を使う |
| サーバーのテレポートに猶予を設けない | 自分のテレポートがプレイヤーにフラグを立てる | まず MoveGuard.grace(player, s) を呼び出す |
| プロンプトの親が未アンカー | どこからでもプロンプトを使用できる | SetNetworkOwner(nil) を設定するか、アンカーする |
回答に InvokeClient を使う | サーバースレッドが永久に停止する | RemoteEvent で要求と応答を行い、タイムアウトを設ける |
UnreliableRemoteEvent にバッチをまとめる | 1,000バイトを超えると通知なしにドロップされる | バッチには信頼性の高い方式を使い、payload_probe で測定する |
| 「現在」の状態だけでヒットを判定する | ラグがあると有効なヒットが拒否される | 巻き戻しウィンドウまたはコーンを使う |
| 壁の判定で移動中のプレイヤーに対してレイキャストする | ラグによって正当な射撃が拒否される | 静的なジオメトリのみを使う |
| ローダーとして ReplicatedStorage の下に LocalScript を置く | クライアントコードが実行されない | RunContext を Client に設定した Script を使う |
MoveTo または character_navigation で Server Authority のテストを駆動する | 何も動かず、すべてのハックがブロックされているように見える | キーを押し続ける(Playtest.press)。まず正当な歩行で移動することを確認する |
引き継ぎ
- scenario-roblox-architecture から受け取るもの:リモート一覧、フォルダ構成、状態の保存場所。
- scenario-roblox-gameplay から受け取るもの:検証対象となるヒットボックス、飛び道具、アビリティのルール。
- scenario-roblox-data に引き渡すもの:保存前に検証し、有限値であることとサイズを確認した値、および 取引と購入のアトミック性に関する質問。
- scenario-roblox-monetization に引き渡すもの:
ProcessReceiptからの付与のみ、およびpurchase-signalの調査結果。 - scenario-roblox-performance に引き渡すもの:ペイロードサイズ、送信レート、Server Authority の シミュレーション予算。
- バッファーのパッキングと Parallel Luau に関する質問は scenario-roblox-luau に尋ね、オフライン監査の CI 接続については scenario-roblox-tooling に尋ねます。
Roblox に関する最新メモ
- Server Authority は 2026-07-09 に正式リリースされました。
AuthorityModeを Server に設定すると、StreamingEnabled、 Deferred signals、UseFixedSimulation、NextGenerationReplication、PlayerScriptsUseInputActionSystem が有効になります。 - スクリプトから Studio の MCP コンテキストでこれらの設定を読み書きすることはできません(「RobloxScript capability」が不足しています)。Rojo プロジェクトまたは Properties パネルで設定してください。動作で確認します: Deferred signals、入力のみの移動。
BindToSimulation内ではtime()を使用してください。task.deferはシミュレーションステップの外に移動します。エフェクトは シミュレーション内ではなく RenderStepped に配置してください。RaycastParams.ExcludeInstancesとIncludeInstancesは、FilterDescendantsInstancesとFilterTypeに 置き換わりました(2026-04-07)。BlacklistとWhitelistは廃止されています。- Network Simulator はベータ版で、
NetworkSettingsを制御します。旧式のIncomingReplicationLagは 引き続き存在しますが、使用するツールではありません。 - 待機する API には
Asyncサフィックスが付いています(BanAsync、UnbanAsync、GetBanHistoryAsync)。
参考資料
- references/expert-notes.md:専門家による原則と判断。タイムスタンプと 実測値を含みます。
- references/procedures.md:ステージ P1〜P11 の完全なコード、テスト ID、 実測結果。動かせるパーツと検知器のチェック(P6)、Server Authority 移行リスト(P11)、 順序に関する落とし穴を含みます。
- references/critique.md:自身の出力を評価するための合格・不合格基準。
- references/gui-paths.md:同じ作業に使用する Studio のメニューと、スクリプトによる 代替手段。
- references/sources.md:すべてのドキュメントと動画。認証情報と タイムスタンプを含みます。
- scripts/rbx_net.py:監査、キットのツリー表示、ファジング、ペイロード調査、レイテンシー、 NetLog のヘルパー。
- scripts/agentkit/networking/:
Guard、RateLimit、Suspicion、Net、HitCheck、MoveGuard、Exploit、NetAudit、lune_net_audit.luau。