想象一个带有滚动关卡的太空射击游戏。有哪些方法可以防止恶意玩家为了自己的利益而修改游戏?他可以做的很难限制服务器端的事情是自动瞄准,在可见区域之外偷看,速度黑客和其他事情。
有什么方法可以防止这种情况?假设服务器是任何语言,并且客户端通过 WebSocket 连接。
始终假设代码是 100% 可破解的。想办法防止客户端完全重写(为了作弊)作弊。这些可以是诸如编写安全游戏协议的方法、服务器端检测等。
想象一个带有滚动关卡的太空射击游戏。有哪些方法可以防止恶意玩家为了自己的利益而修改游戏?他可以做的很难限制服务器端的事情是自动瞄准,在可见区域之外偷看,速度黑客和其他事情。
有什么方法可以防止这种情况?假设服务器是任何语言,并且客户端通过 WebSocket 连接。
始终假设代码是 100% 可破解的。想办法防止客户端完全重写(为了作弊)作弊。这些可以是诸如编写安全游戏协议的方法、服务器端检测等。
服务器为王。客户端是可破解的。
您想要对 websocket 做两件事。
将游戏动作发送到服务器并从服务器接收游戏状态。
你渲染游戏状态。然后您将输入发送到服务器。
你可以不解决由涅槃代码这些问题。客户端上的代码仅用于处理输入和显示输出。所有逻辑都必须在服务器上完成。
您只需要编写服务器端验证。唯一的问题是,由于复杂性,游戏输入比表单输入更难验证。这与您为确保表单安全所做的完全相同。
不过,您需要非常小心您的“输入有效”检测。您不想从您的游戏中踢出/禁止高技能玩家。很难在机器人检测过于宽松和机器人检测过于严格之间取得平衡。机器人检测的整个领域总体上非常困难。例如,Quake 有一个自动瞄准检测功能,可以在当天踢回合法的熟练玩家。
至于阻止机器人连接到您的 websocket,请直接在您的多人游戏上设置单独的 HTTP 或 HTTPS 验证通道以增加安全性。使用多个 Http/https/ws 通道来验证客户端是“官方的”,充当某种形式的握手。这将使直接连接到 ws 变得更加困难。
例子:
想想一个简单的多人游戏。基于 2D 房间的赛车游戏。多达 n 个用户在平面 2D 平台游戏地图上竞相从 A 到 B。
假设您有一个傻瓜式安全系统,其中有一个复杂的身份验证通过 HTTPS 通道,因此用户无法直接访问您的 websocket 通道并被迫通过浏览器。您可能有一个处理身份验证的 chrome 扩展程序,并强制用户使用它。这减少了问题域。
您的服务器将发送客户端渲染屏幕所需的所有视觉数据。您无法隐藏这些数据。无论你尝试什么,一个愚蠢的黑客都可以拿走你的代码并在调试器中减慢它的速度,直到他剩下的只是围绕你的 websocket 的原始包装器。他让你运行整个身份验证,但没有什么可以做,以从阻止他这样做,剥出你写任何JavaScript阻止他。你所能做到的就是限制足够熟练的黑客访问你的 websocket 的数量。
因此,黑客现在在 chrome 沙箱中拥有您的 websocket。他看到了输入。当然,您的赛道是动态且唯一生成的。如果你有一定数量的它们,那么黑客就可以预先设计出最佳的比赛路线。您发送的用于可视化此地图的数据可以比人类与游戏的交互更快地呈现,并且可以计算赢得赛车游戏的最佳动作并将其发送到您的服务器。
如果您试图禁止对您的地图数据react过快的玩家并将其称为机器人,那么黑客会对此进行调整并增加延迟。如果您尝试禁止玩得太完美的玩家,那么黑客会调整它并使用随机数来玩得不那么完美。如果您在地图中放置只有算法机器人会落入的陷阱,那么可以通过了解它们、通过反复试验或机器学习算法来避免它们。要绝对安全,您无能为力。
你只有ONE选项,以绝对避免黑客的攻击。那就是建立你自己的不能被黑客入侵的浏览器。将安全机制构建到浏览器中。不允许用户在运行时实时编辑 javascript。
在服务器端,有两个选项:
1) 全服务器端游戏
每个客户端将他们的“动作”发送到服务器。服务器执行它们并将相关数据发回。例如,一艘船要向北移动,服务器计算它的新位置并将其发送回来。服务器还会发送一个可见船只的列表(解决 maphacks)等。
2) 全客户端游戏
每个客户端仍然将它们的动作发送到服务器。但是为了减少服务器上的工作量,服务器不执行操作而是将它们转发给所有其他客户端。然后客户端同时解决所有操作。因此,每个客户端都应该得到相同的游戏。每个客户端定期向服务器发送其绝对数据(船舶位置等),服务器检查所有客户端数据是否相同。否则,游戏不同步,肯定有人在进行黑客攻击。
第二种方法的缺点是一些黑客仍然未被发现:例如地图黑客。作弊者可以注入代码以便他看到所有内容,但仍然只将他通常应该能够看到的数据发送到服务器。
——
在客户端,有 1 个选项:一个 javascript 组件,它扫描游戏代码以查看是否有任何修改(例如,修改代码以呈现不可见但向服务器发送不同验证数据的对象)。
显然,黑客可以轻松禁用该组件。要解决这个问题,您可以强制客户端定期从服务器重新加载组件(服务器可以检查用户是否定期请求脚本文件)。这引入了一个新问题:黑客只是通过 AJAX 定期请求组件,但阻止它运行。为避免这种情况:让组件重新下载自身,但对自身进行稍微修改的版本。
例如:让组件位于 yoursite/cheatdetect.js?control=5。服务器会生成一个稍微修改的cheatdetect.js,以便在下一次迭代中,必须下载cheatdetect.js?control=22(例如)。如果控制机制足够复杂,黑客将无法预测接下来请求哪个控制号,必须执行cheatdetect.js才能继续游戏。
您无法真正阻止任何人修改您的 JS 或编写 GreaseMonkey 脚本。但是,您可以通过缩小脚本以及使代码尽可能神秘来使它们变得困难。甚至可能会加入一些虚假的方法或变量,这些方法或变量什么也不做,只是用来赶走攻击者。但是如果有足够的时间,这些方法都不是完全万无一失的,因为一旦您的代码到达客户端,它就不再是您的了。
我什至想到实现这一点的唯一方法是修改您的 Javascript 以充当客户端,然后设计一个中央服务器机制来验证从该客户端发送的数据。这可能是要实施的重大更改,并且很可能会使您的项目更加复杂。但是,如前所述,如果应用程序完全在客户端上运行,那么客户端几乎可以对您的脚本做任何他们想做的事情。保护它的唯一方法是使用受信任的机器来处理验证。
他们不必接触您的客户端代码——他们只需嗅探并实现您的 Websocket 协议并编写一个伪装成人类玩家的小代理。
更新:这个问题有几个部分,我的脑子里没有答案,但是可以考虑到这些问题来评估各种选项:
当然,您抛出的许多障碍都可以避开,但对玩家和您而言,成本是多少?参见“消耗战”。