我需要关注游戏服务器的安全性吗?

Do I need to concern security about my game server?

我有一个游戏服务器,客户端可以通过 TCP 连接和通信。任何知道IP和端口的设备都可以连接到服务器。

我想知道是否需要为服务器添加一些安全措施。例如,

(1) 为消息 sent/received 添加一些加密。 (防止协议内容泄露)

(2) 在消息中添加一些密钥,如果服务器在解密后无法识别密钥,消息将被丢弃。 (防止未知connections/messages泛滥)

你认为这些东西有必要吗?对于这样的游戏服务器,我还应该添加什么吗?

我宁愿将此发布到 gamedev 问题,但那里的模组显然比这里快。在您引用我的话之前,我想指出以下内容并非基于 100% book-knowledge,我也没有任何这些主题的学位。如果您知道得更多,请改进此答案,而不是发表评论 and/or 竞争。

这是我从研究 and/or 经验中收集到的 client/server/security 问题的一个非常全面的列表:

数据
"back-end"服务器里面有大家的用户名、密码、信用卡信息等等,应该是个堡垒。该服务器仅用于身份验证,应位于私有子网上;只有当收到 well-formed 登录请求时,它才会与登录服务器通信,并且只会回复 "allow" 或 "deny"。如果您获取他人的个人信息,您有义务保护它,明智的做法是 off-load 将一切责任 security-related 交给专业人士或托管公司。本服务器没有non-critical攻击;如果它被破坏,你就完了。 Many/most/all 公司现在在其他公司的 back-end 信用 card/billing 系统之上绘制他们漂亮的登录屏幕。

登录
与登录服务器的连接应该是安全的。登录服务器只是 public 登录机制、私有数据存储和 client/server 连接状态之间的消息泵。出于安全目的,对登录系统的任何 HTTP 访问都应托管在单独的 HTTP 服务器上; WWW 服务器崩溃不应该关闭您的在线游戏(我的意见)。

World/UDP
成功登录和验证后,服务器通知客户端开始侦听 "bulk data" 或在特定 UDP 端口(可以是随机的和 per-connection-attempt )上启动 in-bound 连接。无论哪种方式,服务器都应保持沉默并等待客户端通过某种类型的握手进行 IDENT 以验证 "alleged client" 实际上是您的代码。当服务器按顺序要求输入时更容易猜测;相反,依赖于客户端在连接到世界时知道正确的握手,并丢弃那些不知道的。要使用的正确握手可以是 CPU clock-ticks 或其他任何函数。从那时起,TCP 将被最低限度地使用 and/or 断开连接。初始批量数据是宣传当前 server-side 软件修订版的好地方,因此 out-of-date 的客户端可以更新。可以在多个服务器之间分配一个公共的 UDP 端口池,并且客户端可以 load-balanced 进入正确的 port/server。在游戏中,"zone transfers" 可能意味着与一个 server/port 断开连接并重新连接到另一个 server/port。在 MMO 中,这通常显示为 <2 秒的加载屏幕;有足够的时间断开连接、重新连接、开始获取数据并同步到新的服务器时钟,更不用说实际的内容加载了。

"World server" 描述了单个 multiple-client、state-pumping 线程 运行 在单个 blade 的单个处理器的单个内核上。第一,物理上,server-of-worlds 可以同时拥有多个世界 运行。世界可以是动态的 split/merged(以 quad-tree 的方式),再次将客户端划分为 load-balancing;服务器之间的同步以 LAN 速度或更高速度进行。世界服务器可能只会为 UDP 连接提供服务,除了处理 state-changes to/from UDP 连接外应该没有其他事情可做。 UDP 为 "blind, deaf, and dumb"、so-to-speak。发送消息时没有流量控制,没有错误检查等;它们基本上被认为是在发送后立即收到,但实际上可能会迟到、顺序错误或永远不会到达。使用 UDP,服务器和客户端都不会停止,hand-shaking、error-correcting 或等待数据。消息需要 time-stamps,因为它们可能会迟到 and/or out-of-order。如果 UDP 通道被阻塞,将有效客户端动态切换到另一个(可能是随机的)端口。世界服务器仅启动与成功通过身份验证的客户端的 UDP 连接,并忽略所有其他流量(世界服务器与 HTTP 和其他所有内容分开托管)。

过于简化,仅以位置数据为例,每个客户端一遍又一遍地告诉服务器"Time:Client###:(X, Y)"。如果服务器没有听到,哦,好吧。服务器一次又一次地对每个人说 "Time:listOfClients(X, Y)"。如果一个或多个客户没有听到,哦,好吧。

这意味着在客户端使用prediction/extrapolation;客户端将需要 "guess" 应该 发生什么,然后在他们再次开始获取数据时更正自己以同意服务器。任何时候你得到一个带有 "future" 时间的数据包,即使这个数据包没有意义或没有用,你至少可以将客户端时钟提前到那个点并丢弃任何 now-late 数据包,帮助落后的客户赶上。

Un-verified假设:
除了现有的安全问题,我没有看到两个或多个客户端无法保持独立的原因,但是 server-managed,每个客户端之间的 UDP 通道其他。除了服务器之外,通过在关闭 game-proximity 内通知其他客户端,客户端本身可以帮助 load-balance。服务器应该始终验证客户端所说的 could/should/would 发生了什么,并且能够撤消所有这些并将两个客户端重置为它自己的 known-good 状态。客户能够在内部共享的信息应该受到严格限制;基本上只是 most-time-critical 位置 and/or state-data。可能不允许客户端请求特定信息,并且再次仅依赖 "dumb" 广播。这开始接近 distributed/cloud 计算,其中客户端实际上在做大量的服务器工作,而服务器只是观察并 "referees," 在适当的时候呼叫犯规。

客户端 1 - "I fought Client2 and won"
客户端 2 - "I fought Client1 and won"
服务器 - "I watched and Client2 cheated. Client1 wins. (Client2 is forced to agree)"
服务器甚至不一定需要观看;如果Client2以unusual/impossible方式损坏Client1,Client1可以向服务器请求仲裁

Side-effects
如果玩家四处移动,但数据未到达服务器,则玩家体验 "rubber-banding",玩家 看起来 在客户端移动,但是 server-side,他们不是。当客户端获得下一个服务器状态时,客户端会将播放器捕捉到服务器停止获取更新时他们所在的位置,从而产生 rubber-band 效果。

这也经常以另一种方式表现出来。如果服务器发现玩家在移动,然后没有收到 "stopped moving" 消息,服务器将为所有其他客户端预测他们的继续路径。例如,在 MMO-RPG 中,您可以直接在 into/at 墙上看到 "lagging" 玩家 运行。


我能想到的最后一件事就是基本的代码安全性。如果您的游戏是可修改的,这一点尤其重要。根据定义,Mod 是用户将自己的代码插入您的代码的一种方式。如果您对您泄露的 "API" 访问量粗心,那么不可避免地,有人会觉得需要恶意。如果您使用的语言需要它,请特别注意字符串 termination/handling。不要从 plain-text ASCII 内容文件构建游戏。如果您的游戏只有一个 "text box,",就会有人试图喂 HTML/LUA/etc。代码进去。

最后,路径应尽可能使用适当的系统变量以避免平台恶作剧and/or访问冲突(x86/x64,ProgramFiles 中没有保存游戏等)