以可靠的方式找出延迟

时间:2017-08-08 06:30:21

标签: networking latency exploit anti-cheat

背景:我正在开发一款小游戏并使用播放器的延迟来lag compensation。游戏是开源的,所以目前对一个非常容易的任务是对系统进行逆向工程并延迟响应时间来人为地增加报告的延迟,从而可能产生不公平的优势。

我目前的延迟检索策略是:

  • 每隔固定的时间间隔,我发送一条标记为" ping"对一个球员。 (这与ICMP无关)
  • 此ping消息包含一个特殊的" ping"操作码和序列号
  • 的有效负载
  • 一旦客户收到所述消息,他就会发回一个带有" pong"操作码和具有相同序列号的有效负载
  • 当服务器收到标记为" pong"的消息时,它会计算发送和接收之间传递的时间。这是往返时间
  • 我们的延迟是rtt / 2

在伪代码中

服务器:

function now() {
    return current UTC time in millis
}

i = 0
function nextSequence() {
    return i++
}

sendingTimestamps = []
function onPingEvent() {
    id = nextSequence()
    sendingTimestamps[id] = now()
    sendPingMessage(id)
}

function onPongReceived(id) {
    received = now()
    sent = sendingTimestamps[id]
    rtt = received - sent
    latency = rtt / 2
}

客户:

function onPingReceived(id) {
    sendPongMessage(id)
}

正如您所看到的,客户端很容易在代码中添加延迟以夸大其报告的延迟。

是否有更好的方法来减少客户延迟,以减少作弊的空间?

1 个答案:

答案 0 :(得分:2)

以下答案是评论中讨论的主题摘要,以便将它们集中在一个地方。

延迟补偿应该依赖于事件的精确时间戳而不是平均数据包延迟

即使连续两个数据包,转换时间也可能会发生巨大变化。测量平均延迟的建议方法,并假设每个接收的数据包在ms“前”发送“延迟”以进行滞后补偿,这种方法太不准确了。应该采用以下方案:

服务器开始模拟世界,并向所有客户端发送命令START。客户端启动模拟世界并从其创建计数滴答。每当客户端发生任何事件时,客户端都会将其带有时间戳发送给服务器。就像“用户在刻度#183处按下了火”。服务器对游戏的仿真由于数据包转换时间而遥遥领先,但服务器可以“及时回溯”来处理用户的订单并解决后果。

时间戳和事件仍然可以伪造

验证客户输入的AFAIU问题通常无法解决。客户端中实现的任何算法都可以重新创建为虚假事件/时间戳/数据包。封闭的代码可以颠倒,所以它不是答案。即使是像反恐精英或OverWatch这样的全球传播游戏都有骗子,尽管它们是由大公司开发的,我敢打赌,这些公司有独立的部门专注于游戏安全。一些公司开发类似模块的防病毒软件,它可以检查游戏文件的完整性或部分RAM快照的散列,但它仍然可以被绕过。

问题是伪造算法所需的努力程度。需要的努力越多,那就越少。简单的时间戳验证如下:

  1. 如果您在事件#1之后在TCP流中收到事件#2,但其时间戳在事件#1之前,则它是伪造的。

  2. 如果时间戳远远落后于服务器的时间,那么警告并踢出极差的延迟。如果它是一个真正的玩家,无论如何游戏对他来说都是无法玩的,否则你会踢黑客。如果我没弄错的话,CS服务器会这样做。