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