关于 roblox-security
roblox-security 是面向 Roblox 开发者的游戏安全技能,重点介绍服务器端设计。内容涵盖参数校验、限流、移动与战斗检查、经济系统保护及违规检测。
主要功能
- 01服务器端校验与权威控制
- 02限制客户端触发操作的频率
- 03安全处理提示与触碰事件
- 04验证移动与战斗行为
- 05保护经济系统与购买流程
- 06违规检测与处置建议
适用场景
- 01审查 RemoteEvent 和 RemoteFunction 处理逻辑
- 02加固战斗与移动系统
- 03保护交易和游戏内购买
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ el4cteo/ roblox-skills --skill roblox-security安装后在 Claude Code 中输入/roblox-security确认已加载。
附带文件references/checklist.md
详细介绍
Roblox 安全
攻击者完全控制自己的客户端:他们可以运行任意 Luau、读取所有已复制的脚本
(反编译后)、以任意参数和频率触发任何远程事件、修改任意本地属性(WalkSpeed、
提示词 Enabled、MaxActivationDistance),并移动他们拥有网络所有权的任何对象。
客户端反作弊充其量只能稍微增加攻击难度。安全性取决于服务端设计。
核心规则
- 由服务端决定。 客户端发送意图(“我按下了攻击键,目标瞄准这里”),而不是结果 (“我造成了 50 点伤害”“给我 100 个金币”)。
- 验证每个
OnServerEvent/OnServerInvoke的每个参数:类型、结构、范围和有限性。 - 验证上下文:玩家是否存活、是否在范围内、是否处于冷却状态、是否拥有该物品、是否允许执行操作?
- 对客户端可触发的一切操作进行速率限制(远程事件、提示、触碰、点击)。
- 将机密保留在服务端:服务端代码放在
ServerScriptService/ServerStorage中;通过HttpService:GetSecret()获取 API 密钥;绝不将尚未发布的内容放入生产环境。 - 优先采用静默缓解措施(丢弃、限制、纠正状态),而非立即踢出;对重复出现的信号逐步升级处置。
参数验证工具包
--!strict
-- ServerScriptService/Server/Validate.luau
local Validate = {}
function Validate.number(value: unknown, min: number, max: number): number?
if typeof(value) ~= "number" or not math.isfinite(value) then
return nil -- rejects NaN and ±inf (NaN fails every comparison, so range checks alone don't catch it)
end
if value < min or value > max then
return nil
end
return value
end
function Validate.integer(value: unknown, min: number, max: number): number?
local n = Validate.number(value, min, max)
return if n and n == math.floor(n) then n else nil
end
function Validate.string(value: unknown, maxLength: number): string?
if typeof(value) ~= "string" or #value > maxLength or utf8.len(value) == nil then
return nil -- also rejects invalid UTF-8 (which DataStores refuse)
end
return value
end
function Validate.vector3(value: unknown, maxMagnitude: number): Vector3?
if typeof(value) ~= "Vector3" then
return nil
end
if not (math.isfinite(value.X) and math.isfinite(value.Y) and math.isfinite(value.Z)) then
return nil
end
return if value.Magnitude <= maxMagnitude then value else nil
end
-- Accept only a real instance of the expected class that lives under a trusted container.
-- Exploiters can send tables shaped like instances ({ ClassName = "Part", ... }).
function Validate.instanceIn(value: unknown, className: string, container: Instance): Instance?
if typeof(value) ~= "Instance" or not value:IsA(className) or not value:IsDescendantOf(container) then
return nil
end
return value
end
function Validate.enum<T>(value: unknown, allowed: { [T]: boolean }): T?
if allowed[value :: any] then
return value :: any
end
return nil
end
return Validate
- 将
player之后传入处理程序的每个参数都视为unknown,并用这些辅助函数缩小其类型范围。 - 根据 ID 在服务端表中查找物品(
ITEMS[itemId]);绝不从客户端数据或客户端可以引用的已复制NumberValue中读取价格或属性。 - 限制表的大小,并防御性地遍历客户端表(键可能类似 NaN、嵌套或过大)。
速率限制(令牌桶)
--!strict
local Players = game:GetService("Players")
type Bucket = { tokens: number, last: number }
local function newLimiter(capacity: number, windowSeconds: number)
local refillRate = capacity / windowSeconds
local buckets: { [Player]: Bucket } = {}
Players.PlayerRemoving:Connect(function(player)
buckets[player] = nil
end)
return function(player: Player): boolean
local now = os.clock()
local bucket = buckets[player]
if not bucket then
bucket = { tokens = capacity, last = now }
buckets[player] = bucket
else
bucket.tokens = math.min(capacity, bucket.tokens + (now - bucket.last) * refillRate)
bucket.last = now
end
if bucket.tokens >= 1 then
bucket.tokens -= 1
return true
end
return false
end
end
local allowAttack = newLimiter(5, 1) -- bursts of 5, refills 5/second
print(allowAttack)
特别要对以下昂贵或易遭利用的操作进行速率限制:DataStore/Badge/HTTP 调用(它们各自有调用额度)、克隆大型模型、传送、发放货币,以及向所有客户端广播的任何操作。
客户端触发的实例并不安全
| 对象 | 攻击者可以做什么 | 服务端必须做什么 |
|---|---|---|
ProximityPrompt | 即使禁用也能触发事件;在本地更改距离、视线检测和 HoldDuration。只有 Triggered 会检查距离。 | 重新检查启用状态、与角色的距离、存活状态和冷却状态。 |
ClickDetector | 即使禁用,也能从任意距离触发。服务端完全不做检查。 | 同上。 |
DragDetector | 继承的点击事件未经检查;拖动只受 Enabled 和 PermissionPolicy 限制。 | 在服务端验证拖动结果。 |
客户端拥有的部件上的 Touched | 伪造或抑制触碰事件。 | 使用服务端的距离/重叠查询进行验证。 |
如果这些对象位于客户端可以拥有的未锚定部件中,攻击者就能将部件拉到自己身边:将部件锚定,或使用 part:SetNetworkOwner(nil) 将所有权设为服务端。
网络所有权和移动
客户端拥有其角色的物理模拟权,因此可以传送、飞行、穿墙、加速作弊、将其他玩家甩飞(使用 NaN/超大速度),并抑制 Touched。以下方案按效果从强到弱排列:
- 服务端权威控制(Workspace
AuthorityMode = Server;已完全发布,可选择启用):服务端使用客户端预测和回滚来模拟移动,从而消除移动作弊。 参见roblox-physics。 - 服务端移动检查:按时间间隔将水平(XZ)位移与最大速度及延迟容差进行比较;对合法传送进行豁免(由你移动玩家时,在服务端设置标记);将玩家回弹到最后一个有效位置,而非踢出。
- 让游戏玩法关键的未锚定部件由服务端拥有:
part:SetNetworkOwner(nil)。
战斗验证(命中报告)
客户端发送起点、方向/目标部件和时间戳。服务端检查:
- 起点是否接近角色的服务端位置(根据
player:GetNetworkPing()调整容差)。 - 目标是否存活、是否为敌人、是否在武器射程内;声称的命中点是否接近目标的服务端位置。
- 对静态几何体进行服务端射线检测,确认起点与目标之间没有墙壁。
- 射速、弹药、装填/冲刺状态均由服务端跟踪。
经济、交易、购买
- 货币、库存和价格只存在于服务端。客户端发起请求;服务端检查余额并以原子方式应用更改。
- 交易:完整验证双方,然后提交双方,然后保存双方;任何失败都回滚一切。警惕“交易后在保存前离开”导致的复制漏洞:交易期间锁定物品,并在交易后立即保存。
- Robux 购买:仅在
MarketplaceService.ProcessReceipt(开发者产品)中发放,或在服务端所有权检查(通行证)之后发放。绝不要信任来自客户端的PromptProductPurchaseFinished。参见roblox-monetization。
保密性
- 任何会复制的
LocalScript、客户端Script或ModuleScript都可能被反编译——即使已禁用或从未被 require。不要把仅服务端分支混入共享模块。 - 任何会被复制的内容(模型、UI、属性)都可能被数据挖掘。将未发布内容放在独立的私有 universe 中,而不是隐藏在生产环境中。
- 客户端可以传送到 universe 中的任何 place:在 Creator Dashboard 中设置 Access Control for Places → Secure within universe only,并在受限 place 的加入时验证资格(默认拒绝)。
- 绝不要把 API 密钥放在脚本或属性中;使用体验内 Secrets 存储(
HttpService:GetSecret)。
检测与后果
在验证之上叠加服务端启发式检测:最快可能的完成时间、资源获取速率、非人类般规律的操作节奏、正常客户端不会触发的蜜罐 remote。累积怀疑分数;基于多个信号采取行动。阶梯:静默记录 → 静默缓解 → 限制功能 → 踢出/封禁。延迟可见后果,使作弊者无法二分探测你的检查。
--!strict
local Players = game:GetService("Players")
local function banForExploiting(player: Player, evidence: string)
local ok, err = pcall(function()
Players:BanAsync({
UserIds = { player.UserId },
Duration = 7 * 24 * 60 * 60, -- seconds; -1 = permanent
DisplayReason = "Exploiting detected.", -- shown to the user (max 400 chars, filtered)
PrivateReason = evidence, -- visible to you only
ExcludeAltAccounts = false, -- also ban detected alt accounts
ApplyToUniverse = true,
})
end)
if not ok then
warn("BanAsync failed:", err)
player:Kick("Exploiting detected.")
end
end
return banForExploiting
为 Ban API 启用 Players.BanningEnabled。优先使用可逆、有时限的封禁(检查 Players:GetBanHistoryAsync 以升级);对检测规则进行版本管理,并监控误报率。
安全审查清单和常见易受攻击代码模式:references/checklist.md。
相关技能
roblox-networking、roblox-physics(所有权、服务端权威)、roblox-data-stores、roblox-monetization、roblox-code-review。