Caputchin
理解 Caputchin

游戏反作弊

访客玩上几秒的那个游戏是你看得见的那部分。它底下是那套让游戏算作一个人类证明的反作弊系统。Caputchin 借用竞技多人游戏对付作弊者的那套打法:服务器对每个回合权威、游戏在一个锁死的沙箱里跑、而结果通过重放玩家的输入来重新推导。这个游戏可以被玩,但作不了假。

这是第三道验证关卡,和 proof of work探测 叠在一起。它在 安全 页上按密钥配置。

这个生命周期

一个回合走过三个阶段:在游玩前于服务器上搭建、在游玩中于浏览器里沙箱化地跑、并在游玩后于服务器上重新核验。

回合之前:服务端权威的搭建

决定这个回合 是什么 的一切都发生在服务器上,绝不在浏览器里。这就是多人游戏反作弊里那条“永不信任客户端”的原则:客户端发送意图,服务器决定现实。

  • 一张签名的、一次性的票据 铸造这个回合。它短时有效,且只能花一次。一张被截获的票据无法被重放成第二次通过。
  • 游戏和它的随机种子在服务端被选定,并装在票据里。浏览器无法挑一个更容易的游戏或一个更友好的种子,因为它从不做那个选择。
  • 每次都从合格池里换一个不同的游戏。 一个求解器从不知道它会面对哪个游戏,所以它无法在单一的静态目标上预先训练。运营者可以收窄轮换,但服务器总是从被允许的集合里挑。这个池本身只包含通过了一次索引时一致性检查的游戏。见 构建一个应用市场游戏

回合之中:一个沙箱化的游戏

游戏在访客的浏览器里跑,但在一道既保护访客站点、又保护这个回合完整性的边界之内。

<caputchin-game> 把每个游戏挂载在一个没有同源访问权的隔离 iframe 里,于是这个游戏有一个不透明的来源,够不到宿主页的 cookie、存储、DOM 或同源网络。它内联的 content-security-policy 把脚本钉死到恰好是这个游戏的包,并挡住出站的网络调用,而这个包在运行前会对着一个已知的哈希被检查(不匹配则失败关闭)。宿主页自己的安全策略原封不动。精确的沙箱和策略形状记录在 Caputchin 如何沙箱化游戏 里。

要点:游戏默认不被信任并被收容。它无法把任何东西外泄,也无法篡改它所嵌入的那个页面。

回合之后:确定性回放

当访客完成时,浏览器提交记录下来的输入轨迹。服务器不会就结果听信浏览器的话。它重跑这条轨迹。

  • 回合在服务器上被重新模拟,在同一个服务端派生的种子下,在一个没有网络访问、带一个硬时间预算的密封隔离体里。这就是确定性锁步在策略游戏里所依赖的同一种性质:相同的种子加相同的输入,重现相同的游玩。一条没真正通过游戏的轨迹不会重现出一个通过的结果。
  • 通过还是失败从那次回放里取,绝不从浏览器报告的一个数字里取。一个客户端无法声称一个它没挣到的分数。
  • 一个签名的令牌仅当回放确认了这次游玩时才被签发。 当你的后端日后在验证时确认它时,那个令牌本身也是一次性的。

Caputchin 不做什么

大多数游戏式和交互式 CAPTCHA 倚靠行为信号:鼠标轨迹熵、点击时机、喂给一个分类器去猜机器人对真人的设备遥测。Caputchin 有意不这样。它不采集玩家的任何行为画像。它不去猜这些输入是 如何 产生的,而是从第一性原理重新推导它们 是否 真的通过了游戏。这既是一种隐私姿态、也是一种安全姿态:没有行为模型可骗,只有物理可重现。

一个诚实的局限

关卡只和游戏一样强。 反作弊机件证明一个回合是被真正玩过的、没作假,但它无法让一个简单的游戏变难。一个微不足道的游戏(一个静态棋盘、获胜的一步在 DOM 里可读、“点红点即过”)对一个脚本来说求解便宜,而确定性回放会忠实地确认那些脚本化的输入获胜,因为它们确实获胜。对机器人的抵抗力来自游戏本身难以被程序化地求解:快速、感官、零点几秒的反应,且没有解坐在 DOM 里。反作弊层保证这次游玩是真的;游戏的设计决定真实的游玩是否难以被自动化。怀着这个去挑选和构建游戏,见 构建一个应用市场游戏

通过还是失败由每个游戏自己的逻辑决定;服务器忠实地重跑那个逻辑,但不去质疑一个给定游戏认为什么算获胜。游戏反作弊在和 proof of work探测 以及一个密钥其余的 安全设置 组合在一起时最强。

本页内容