有什么好方法可以防止JavaScript多人游戏中的作弊行为?

时间:2011-03-09 18:29:00

标签: javascript security multiplayer

想象一下具有滚动水平的太空射击游戏。有什么方法可以阻止恶意玩家修改游戏以使其受益?他能做的事情很难限制服务器端是自动瞄准,在可见区域外窥视,加速黑客攻击和其他事情。

有什么方法可以防止这种情况发生?假设服务器是任何语言,并且客户端通过WebSocket连接。

始终假设代码是100%可攻击的。想办法防止客户完全重写(作弊的目的)作弊。这些可以是诸如编写安全游戏协议的方法,服务器端检测等等。

9 个答案:

答案 0 :(得分:36)

服务器为王。客户是可以破解的。

你想要做的是使用websocket做两件事。

将游戏操作发送到服务器并从服务器接收游戏状态。

您渲染游戏状态。并将输入发送到服务器。

  • 自动瞄准 - 这个很难解决。你必须追求现实主义。如果用户在10ms内击中10次爆头,那么你就踢他了。写一个聪明的作弊检测算法。
  • 在可见区域外偷看 - 只通过向每个客户发送可见区域来解决
  • 加速黑客攻击 - 通过正确处理输入解决。您收到一个事件,用户向前移动并控制他的速度。

您可以 NOT 通过缩小代码来解决这些问题。客户端上的代码 ONLY 用于处理输入和显示输出。 所有逻辑必须在服务器上完成。

您只需编写服务器端验证即可。唯一的事情是游戏输入由于复杂性而难以验证然后形成输入。这与使表单安全的方式完全相同。

你需要非常小心你的“输入有效”检测。你不想踢/禁止游戏中的高技能玩家。很难达到机器人检测过于宽松和机器人检测过于严格的平衡。整个机器人检测领域非常困难。例如,Quake有一个自动目标检测功能,可以在当天重新启动技术熟练的玩家。

至于停止机器人连接到您的websocket,直接在您的多人游戏中设置单独的HTTP或HTTPS验证通道,以增加安全性。使用多个Http / https / ws通道将客户端验证为“官方”,充当某种形式的握手。这将使得更难直接连接到ws。

示例:

想想一个简单的多人游戏。基于2D房间的赛车游戏。最多n个用户使用平面2D平台地图并竞赛从A到B.

让我们假设您有一个傻瓜系统,其中有一个复杂的认证通过HTTPS通道,因此用户无法直接访问您的websocket通道并被迫通过浏览器。您可能有一个处理身份验证的Chrome扩展程序,并强制用户使用它。这减少了问题域。

您的服务器将发送客户端呈现屏幕所需的所有可视数据。你无法掩盖这些数据。无论你尝试什么,一个愚蠢的黑客都可以把你的代码放慢,然后在调试器里慢慢编辑它,直到他所有的东西都是你的websocket的原始包装器。他让你运行整个身份验证,但是你可以做 nothing 来阻止他删除你写的任何JavaScript,阻止他这样做。你所能达到的只是限制了黑客熟练访问你的websocket的数量。

所以黑客现在将你的websocket放在chrome sandbox中。他看到了输入。当然,您的赛道是动态且独特的。如果你有一定数量的黑客,那么黑客可以预先设计出最佳的竞赛路线。您发送的可视化此地图的数据可以更快地呈现,然后人工与您的游戏互动,并且可以计算出赢得您的赛车游戏的最佳动作并发送到您的服务器。

如果您尝试禁止对地图数据反应过快的玩家并将其称为机器人,则黑客会对此进行调整并增加延迟。如果你试图禁止那些玩得太完美的玩家,那么黑客就会调整这个并使用随机数来减少玩法。如果您在地图中放置陷阱,只有算法机器人会陷入困境,那么可以通过试验,错误或机器学习算法来了解陷阱。没有什么可以做到绝对安全。

您只有 ONE 选项可以绝对避免黑客攻击。那就是建立自己的浏览器,不能被黑客攻击。在浏览器中构建安全机制。不允许用户在运行时实时编辑javascript。

答案 1 :(得分:3)

在服务器端,有两个选项:

1)完整的服务器端游戏

每个客户发送他们的"操作"到服务器。服务器执行它们并发回相关数据。例如船想要向北移动,服务器计算其新位置并将其发回。服务器还发送可见船只列表(解决maphacks)等等。

2)完整的客户端游戏

每个客户端仍然将其操作发送到服务器。但是为了减少服务器上的工作量,服务器不会执行操作,而是将它们转发给所有其他客户端。然后客户端同时解决所有操作。结果,每个客户端应该以相同的游戏结束。每个客户端定期将其绝对数据(发货位置等)发送到服务器,服务器检查所有客户端数据是否相同。否则,游戏不同步,有人必须是黑客。

第二种方法的缺点是某些黑客仍然未被发现:例如maphack。骗子可以注入代码,以便他看到所有内容,但仍然只发送他通常能够看到服务器的数据。

-

在客户端,有1个选项: 一个javascript组件,用于扫描游戏代码以查看是否有任何内容被修改(例如,修改代码以呈现不可见的对象,但向服务器发送不同的验证数据)。

显然,黑客可以轻松禁用此组件。要解决此问题,您可以强制客户端定期从服务器重新加载组件(服务器可以检查用户是否定期请求脚本文件)。这引入了一个新问题:黑客只是通过AJAX定期请求组件,但阻止它运行。为了避免这种情况:让组件重新下载,但稍微修改一下。

例如:让组件位于yoursite / cheatdetect.js?control = 5。 服务器将生成一个稍微修改过的cheatdetect.js,以便在下一次迭代中,必须下载cheatdetect.js?control = 22(例如)。如果控制机制足够复杂,那么黑客就无法预测接下来要请求的控制号,并且必须执行cheatdetect.js才能继续游戏。

答案 2 :(得分:3)

尽可能地模糊客户端公开的代码。另外,使用一些魔法。

答案 3 :(得分:1)

没有什么可以阻止任何人修改你的JS或编写GreaseMonkey脚本。但是,通过缩小脚本以及使代码尽可能神秘,您可以使它们变得困难。甚至可能会抛出一些虚假的方法或变量,这些方法或变量什么都不做,但却被用来抛弃攻击者。但是如果有足够的时间,这些方法都不是完全万无一失的,因为一旦你的代码进入客户端,它就不再是你的了。

答案 4 :(得分:1)

他们不必触摸您的客户端代码 - 他们可以嗅探并实施您的Websocket协议,并编写一个假装成人类玩家的小代理。

更新:这个问题有几个部分,我没有自己的答案,但可以考虑这些问题来评估各种选项:

  1. 你愿意去防止作弊有多远?如果你只关心随意作弊,那么有多少障碍足以阻止休闲作弊者?中级Javascript程序员?一位认真的专家?权衡这种欺骗的好处,是否有任何真正有价值的东西,如现金和奖品,或仅仅是声誉?
  2. 你如何高度确信人类正在为你的游戏提供输入?例如,有了足够好的计算机视觉库,我可以在一台单独的机器上为游戏建模,假装是鼠标的计算机,但这相对成本较高(不值得我花时间)。
  3. 如何在协议中创建信任链,以便将(2)的知识传递给服务器,并且您的服务器相对确信您的客户端代码正在发送消息?
  4. 当然,你抛出的许多障碍都可能是侧面的,但玩家和你的成本是多少?请参阅“Attrition warfare”。

答案 5 :(得分:1)

我能想到实现这一点的唯一方法是修改您的Javascript以充当客户端,然后设计中央服务器机制来验证从该客户端发送的数据。这可能是实施的一个重大变化,很可能会使您的项目更加复杂。但是,如前所述,如果应用程序完全在客户端上运行,则客户端可以使用您的脚本执行任何他们想要的操作。保护它使用受信任的机器来处理验证的唯一方法。

答案 6 :(得分:0)

我会使用缩小和AJAX的组合。如果所有的功能和数据都没有加载到页面中,那就更难以作弊。

另一方面,modding对像Id Software这样的公司来说是一个非常有利可图的工具。也许允许对系统进行修改可能会使整个社区的游戏更加愉快。

答案 7 :(得分:0)

您可以在浏览器上编辑javascript并使其正常工作。 有人建议拨打电话查询服务器。因此,在调用服务器后,它将在服务器中进行验证。一旦经过验证,它将进入客户端并执行操作。但我认为即使这不是万无一失的。

例如,。对于基本登录操作:在对服务器进行调用时为角度,后端验证用户名& pwd并且如果经过验证,它将返回到客户端并让用户使用angular登录。

当我说使用angular登录时,它会将内容存储在cookie中,比如用户对象和其他东西。但是用户仍然可以删除正在调用后端的JS代码,并返回TRUE(在需要的地方)并将用户对象(虚拟)插入到cookie和其他对象(无论需要什么)和登录。这是一件非常困难的事情,但它是可行的。在许多情况下,即使编辑/破解代码需要数小时,这也是不可取的。

这在单页面应用程序中是可能的,其中JS文件不会为每个页面重新加载。为了减少被黑客攻击的可能性,我们可以使用缩小的代码。我想如果这样的动作是在后端完成的(比如在Django中登录),那就更安全了。

如果我错了,请纠正我。

答案 8 :(得分:0)

可以实施的其他一些方法:

  • 使脚本难以将目标元素与其他元素区分开。如果可能,请避免使用具有可预测的类和ID名称的div。使用JavaScript而不是使用类来注入样式。像黑客一样思考,让自己受苦。
  • 使用脚本将触发的诱饵。例如,如果威胁向量是使用像素颜色的屏幕抓取算法,则将一些常见的像素颜色扔到非目标元素中。对作弊者而言,对这些非目标的命中似乎无关紧要,但可以检测到。您不希望作弊者知道您为什么知道。
  • 将两次操作之间的最短时间限制为略低于最佳人员水平。最好的玩家会达到那个稳定水平,谁在作弊就无关紧要,并且立即能够比通过侧面调用方法调用更快地检测到任何脚本。
  • 随机数生成器通常是统一的。人性不是。随机数生成器的值可能会在设定的限制范围内,并且分布均匀。自然分布是高斯曲线。如果对分布进行采样,并且在x和y轴上看起来像方波,则100%就是作弊者。对于作弊者来说,检测算法的阈值将是相当困难的,因为它是随机数的导数,而不是随机数分布本身。您还使用的是汇总数据,而不是单个游戏来进行检测,因此如果不了解您的检测算法,对算法进行反向工程将非常困难。
  • 尽可能利用熵。避免可预测的游戏。想象一下在一组赛道上的赛车游戏。每个游戏的牵引力,马力和动量水平可能略有不同。脚本必须非常出色才能击败它。在滚动游戏中,您可以更改人类本能但对于计算机来说困难的因素,例如风力,重力变化等。这也将使它变得更加有趣。
  • 服务器生成的令牌可以用于验证是否使用了UI元素,而不是对代码本身的调用。验证可以在游戏结束时的一次调用中进行处理,将事件与UI元素的哈希码进行比较。令牌应该是带有服务器私钥和UI元素的某些值的哈希。
  • 用他们认为您用来检测作弊的数据欺骗作弊者。例如,对带有虚假后端的虚拟调用对DetectCheat方法的调用。这是老魔术师的把戏。当您用另一只手将卡片滑入卡座时,将您的手在此处挥动。让他们在没有出口的迷宫中浪费大量时间,拖着很多头发。