Как учесть разницу в задержке при проверке различий в местоположении с помощью временных меток (античит)?

Если у вас многопользовательская игра, в которой сервер получает информацию о движении (местоположении) от клиента, вы хотите проверить эту информацию в качестве меры защиты от мошенничества.

Сделать это можно так:

maxPlayerSpeed = 300; // = 300 pixels every 1 second
if ((1000 / (getTime() - oldTimestamp) * (newPosX - oldPosX)) > maxPlayerSpeed)
{
   disconnect(player); //this is illegal!
}

Это простой пример, учитывающий только координаты X. Проблема здесь в том, что oldTimestamp сохраняется, как только последнее обновление местоположения было получено сервером. Это означает, что если в это время произошел всплеск задержки, старая временная метка будет получена намного позже, чем новое обновление местоположения сервером. Это означает, что разница во времени не будет точной.

Пример:

  1. Клиент говорит: я сейчас на позиции 5х10
  2. Всплеск задержки: сервер получает это сообщение на отметке времени 500 (обычно она должна приходить примерно на 30)
  3. .... 1 секунда движения ...
  4. Клиент говорит: я сейчас на позиции 20x15
  5. Нет всплеска задержки: сервер получает сообщение с отметкой времени 1530

Теперь сервер будет думать, что разница во времени между этими двумя местоположениями составляет 1030. Однако разница в реальном времени составляет 1500. Это может привести к тому, что античитерское обнаружение будет думать, что 1030 недостаточно долго, тем самым выбивая клиента.

Возможное решение: позвольте клиенту отправлять временную метку при отправке, чтобы сервер мог использовать эти временные метки вместо

Проблема: проблема с этим решением заключается в том, что игрок может манипулировать клиентом, чтобы отправить недопустимую временную метку, поэтому античитерская система не сработает. Это не лучшее решение.

Также можно просто разрешить скорость maxPlayerSpeed ​​* 2 (например), однако это в основном позволяет взламывать скорость в два раза быстрее, чем обычно. Это тоже не лучшее решение.

Итак: есть ли у вас какие-либо предложения, как исправить эту проблему с "отметкой времени сервера и задержкой", чтобы мои меры по борьбе с мошенничеством были оправданы?


person Tom    schedule 01.11.2009    source источник


Ответы (3)


Нет-нет-нет .. при всем уважении, это все неправильно, и как НЕ ДЕЛАТЬ.

Выход: недоверие своим клиентам. Не заставляйте клиентов отправлять свои позиции, заставляйте их отправлять свои состояния кнопок! Просматривайте состояния кнопок как запросы, в которых клиенты говорят: «Я двигаюсь вперед, если вы не возражаете». Если клиент отправляет сообщение «движется вперед» и не может двигаться вперед, сервер может игнорировать это или делать все, что ему нравится, для обеспечения согласованности. В этом случае клиент только дурачит себя.

Что касается взломов скорости, которые стали возможными благодаря лавинной рассылке пакетов, держите счетчик пакетов. Удалять клиентов, которые отправляют больше пакетов в течение определенного периода времени, чем разрешено настройками. Клиенты должны отправлять один пакет за такт / кадр / мировой временной шаг. Пакеты удобно называть в зависимости от времени с шагом целого временного шага. Затем можно идентифицировать и игнорировать избыточные пакеты одного и того же временного шага. Обратите внимание, что отправка одного и того же пакета несколько раз является хорошей идеей при использовании UDP, чтобы предотвратить потерю пакета.

Опять же, никогда не доверяйте клиенту. Это невозможно переоценить.

person Community    schedule 02.11.2009
comment
1) Я использую состояния кнопок, обновления местоположения существуют только для исправлений, которые необходимы из-за задержки 2) Я не доверяю клиенту, потому что, если бы я хотел, я бы не проверял его - просто отправка состояний кнопок не удержит игроков синхронизировано. - person Tom; 03.11.2009
comment
Данные вашего клиента - это состояния кнопок? Это не то, о чем говорится в вашем резюме: Когда у вас многопользовательская игра, в которой сервер получает информацию о движении (местоположении) от клиента, вы хотите проверить эту информацию в качестве меры защиты от мошенничества. Что я имею в виду. под доверием клиентам я имею в виду дать им шанс быть авторитетными. Мировая позиция для клиента авторитетна. Состояние движения вперед - нет. Есть существенная разница. Было бы неплохо, если бы вы могли уточнить, является ли это обходом задержки / задержки или мерой по борьбе с читом. Я запуталась (см. Выше). - person ; 03.11.2009
comment
@Mads, отправка состояний кнопок - это нормально, но в большинстве игр в любом случае придется запускать отдельное прогнозируемое моделирование на клиенте. Таким образом, проблема возвращается к тому, чтобы поддерживать синхронизацию этой клиентской симуляции с сервером в любом случае, и вы получаете меньше проблем с джиттером, если вы отправляете позиции. World of Warcraft - одна из многих игр, в которой клиент сообщает свое собственное положение. - person Kylotan; 03.11.2009
comment
Мэдс, все мое резюме говорит о том, что игра отправляет серверу информацию о перемещении (местоположении). Это верно даже для моей системы состояний кнопок. Как я сказал ранее, эти обновления информации о местоположении предназначены для синхронизации клиентов в случае задержки. Клиент мог отправить неверное обновление местоположения, что привело бы к недопустимому исправлению, чтобы он мог телепортироваться. Вот где на стороне сервера появляется античит. Я не согласен с тем, что все движения должны рассчитываться сервером, профессиональные многопользовательские игры тоже не пошли по этому пути. - person Tom; 03.11.2009
comment
Это может зависеть от типа игры, но интеграция состояния мира на сервере является стандартным де-факто способом сделать это в играх FPS. Напротив, я утверждаю, что большинство игр выбирают эту схему. Если вы не укажете чрезвычайно вескую причину для отправки позиций на сервер, мой ответ все еще остается в силе. То есть я считаю, что это вообще плохая идея. Ничего хорошего из этого не выйдет. Однако проблема с вашей временной меткой не должна быть проблемой. Обеспечьте соблюдение правила, согласно которому один мировой фрейм означает один клиентский пакет. Игнорируйте пакеты из будущего и пакеты из (древнего) прошлого. - person ; 04.11.2009
comment
Может быть, именно такой метод выбирают мелкомасштабные многопользовательские игры, я в этом не очень разбираюсь. Я думаю о массовой многопользовательской игре, и до сих пор все они, кажется, позволяют клиенту выполнять дорогостоящие вычисления, а сервер проверяет это (менее ресурсоемко). Не могли бы вы разработать правило «Обеспечить соблюдение правила, согласно которому один мировой фрейм означает один клиентский пакет». Игнорировать пакеты из будущего и пакеты из (древнего) прошлого. Когда именно вы проигнорируете определенные сообщения и почему? Звучит интересно, но я здесь потерялся. Заранее спасибо. - person Tom; 05.11.2009
comment
Возможно, это было неверным предположением, но я предполагал, что вы использовали интеграцию для улучшения состояния (состояний) сервера и клиента, а также фиксированный временной шаг для моделирования. Скажем, если вы хотите, чтобы симуляция выполнялась со скоростью 50 кадров в секунду, вы получите временную дельту 0,02. Пакеты, которые клиенты и сервер отправляют друг другу, должны находиться точно в одной такой временной дельте. Тогда вы думаете не в секундах, а скорее в количестве кадров моделирования. Поскольку время сервера является авторитетным, любой пакет с будущей меткой времени не является допустимым; клиенты не могут догнать сервер. А слишком старые временные метки просто слишком поздно. - person ; 05.11.2009
comment
Для MMO расходы не являются расчетами. Они визуализируют сцену (большое количество сеток с большим количеством эффектов) и доставку данных. Чем авторитетнее клиент, тем больше данных ему нужно для передачи на сервер. Если сервер является авторитетным, клиент отправляет то, что он хочет сделать, а сервер транслирует эффект всем в пределах досягаемости. Кроме того, если клиенту требуется много времени для обработки чего-либо, синхронизация результата по-прежнему требует взаимодействия с сервером, и вы с большей вероятностью увидите что-то, чего не произошло на клиенте. - person Matt; 06.11.2009
comment
Я тоже так думал. В любом случае вам нужно разумно проверить данные клиента и выполнить моделирование, поэтому в моей голове такая схема просто означает ту же работу, выполняемую на стороне сервера, но с меньшей безопасностью и меньшей стабильностью. Если только кто-то не решил проблему остановки в последнее время. - person ; 06.11.2009

Сглаживайте всплески задержек с помощью фильтрации. Или, другими словами, вместо того, чтобы всегда сравнивать их новую позицию с предыдущей, сравнивайте ее с позицией нескольких обновлений назад. Таким образом, любой краткосрочный джиттер усредняется. В вашем примере сервер может посмотреть на позицию до всплеска задержки и увидеть, что в целом игрок движется с разумной скоростью.

Для каждого игрока вы можете просто удерживать последние X позиций, или вы можете удерживать много недавних позиций плюс несколько более старых позиций (например, 2, 3, 5, 10 секунд назад).

Как правило, вы все равно выполняете интерполяцию / экстраполяцию на сервере в пределах нормальной скорости движения, чтобы скрыть дрожание от других игроков - все, что вы делаете, это распространяете это на свой механизм проверки читов. Все законные ускорения будут происходить после очевидного замедления, и интерполяция помогает скрыть такого рода ошибки.

person Kylotan    schedule 01.11.2009
comment
Положение нескольких обновлений назад все равно будет немного превышать максимально допустимое расстояние из-за одного или двух всплесков задержки между ними. Какой порог, по вашему мнению, стоит добавить во внимание? maxSpeed ​​* 1.1, он же 10%? - person Tom; 01.11.2009
comment
Потенциальная ошибка в вашей системе может существовать в начале игры. Если у вас пока есть только два обновления позиции, вам придется использовать предыдущее. Если это всплеск задержки, это вас пойдет. Если вы проигнорируете первые несколько обновлений на стороне сервера, это будет означать, что игроки всегда могут телепортироваться, перезапустив игру, а затем телепортироваться при каждом перезапуске. Есть идеи по этому поводу? - person Tom; 01.11.2009
comment
Я думаю, что порог должен быть чем-то, что вы выбираете путем экспериментов - вы можете захотеть чего-то другого для FPS, чем, например, для MMO. Но помните, что ваш сервер является авторитетом здесь - если кто-то постоянно работает на 10% быстрее, вы можете просто вернуть его. Что касается недостатка, он является неотъемлемой частью проблемы - чтобы оценить производную значения, вам нужно сначала как минимум 2 выборки этого значения. Опять же, ваш сервер должен быть авторитетным - толкать игрока обратно в разумное место по его направлению движения. Только не думайте, что они обманывают (пока). - person Kylotan; 02.11.2009
comment
Не думаю, что это ответ на вопрос, что делать, когда записей меньше трех. Извините за путаницу, но я не уверен, как это реализовать иначе. - person Tom; 02.11.2009
comment
Если вашей системе измерения требуется 3 записи, вы должны дождаться, пока у вас будет 3 записи, прежде чем начинать проверку измерений на достоверность. Точно так же, как если бы вы наивно измеряли скорость, вам нужно было бы дождаться второй записи. - person Kylotan; 02.11.2009
comment
Это означало бы, что они могут 1) телепортироваться далеко, а затем 2) телепортироваться обратно, и система защиты от мошенничества не сработает. Это неприемлемо. - person Tom; 03.11.2009
comment
Вы бы остановили это, вернув их обратно на вторую позицию, которую они отправили вам, поскольку ваш сервер знает, что они никак не могут там оказаться. Но вы не подумаете, что они обязательно жульничали, пока не соберете еще несколько образцов. - person Kylotan; 03.11.2009
comment
Интересно, поэтому мне пришлось бы комбинировать несколько методов. Ваш и мой. Я не совсем уверен, что наличие нескольких сэмплов решит проблему, поскольку также будет несколько случаев запаздывания, которые могут нарушить баланс разницы во времени. - person Tom; 03.11.2009
comment
Это не столько несколько методов, сколько несколько проблем. Один из них - сглаживание джиттера для получения точных позиций. Другой проверяет потенциальную измену. Они используют одни и те же данные, но должны обрабатывать их по-разному. Довольно часто приходится отбрасывать кого-то назад в менее отдаленную позицию, не предполагая, что они жульничают, чтобы достичь более отдаленной позиции. - person Kylotan; 03.11.2009

Независимо от мнений о подходе, вы ищете порог скорости, который считается «обманом». Учитывая расстояние и приращение времени, вы можете легко увидеть, не продвинулись ли они «слишком далеко» на основе вашего порога читерства.

time = thisTime - lastTime;
speed = distance / time;
If (speed > threshold) dudeIsCheating();

Время, используемое для измерения, - это время приема пакетов сервером. Хотя это кажется тривиальным, он рассчитывает расстояние для каждого движения персонажа, что может оказаться очень дорогостоящим. Лучший способ - сервер вычислить позицию на основе скорости, а это позиция персонажа. Клиент никогда не сообщает положение или абсолютную скорость, вместо этого клиент отправляет «процент от максимальной» скорости.


Уточняю: это было просто для проверки на чит. Ваш код может задерживаться или долго обрабатываться на сервере, что повлияет на ваш результат. Формула должна быть такой:

maxPlayerSpeed = 300; // = 300 pixels every 1 second
if (maxPlayerSpeed < 
    (distanceTraveled(oldPos, newPos) / (receiveNewest() - receiveLast()))
{
   disconnect(player); //this is illegal!
}

Это сравнивает скорость перемещения игроков с максимальной скоростью перемещения. Временные метки определяются тем, когда вы получаете пакет, а не когда вы обрабатываете данные. Вы можете использовать любой метод, который вам нужен для определения обновлений для отправки клиентам, но для порогового метода, который вы хотите определить для определения мошенничества, задержка не повлияет на вышеуказанное.

Получить пакет 1 в секунду 1: символ в позиции 1

Получить пакет 2 в секунду 100: символ в позиции 3000

пройденное расстояние = 2999

время = 99

рейтинг = 30

Обмана не было.

Получить пакет 3 на секунде 101: символ в позиции 3301

Пройденное расстояние = 301

время = 1

рейтинг = 301

Обнаружен обман.

То, что вы называете «всплеском задержки», на самом деле является большой задержкой при доставке пакетов. Но это не имеет значения, поскольку вы не проходите мимо обработки данных, вы проходите мимо момента получения каждого пакета. Если вы сохраните расчеты времени независимо от обработки игрового тика (как и должно быть, как и все, что произошло во время этого «тика»), высокая и низкая задержка влияют только на то, насколько сервер уверен в позиции персонажа, что вы используете интерполяцию + экстраполяцию для решения .

Если клиент недостаточно синхронизирован с тем местом, где он не получил никаких поправок к своему положению, и сильно не синхронизирован с сервером, происходит значительная потеря пакетов и высокая задержка, которую ваша проверка на мошенничество не сможет учесть. Вы должны учитывать это на более низком уровне с обработкой фактических сетевых коммуникаций.

Для любых игровых данных идеальный метод состоит в том, чтобы все системы, кроме сервера, отставали на 100-200 мс. Допустим, у вас есть запланированное обновление каждые 50 мсек. Клиент получает первое и второе. У клиента нет данных для отображения, пока он не получит второе обновление. В течение следующих 50 мс он показывает последовательность изменений, которые уже произошли (т. Е. Воспроизведение с очень небольшой задержкой). Клиент отправляет серверу состояние своих кнопок. Локальный клиент также прогнозирует движение, эффекты и т. Д. На основе этих нажатий кнопок, но отправляет серверу только «состояние кнопки» (поскольку существует конечное количество кнопок, существует конечное количество битов, необходимых для представления каждого состояния, что позволяет использовать более компактный формат пакета).

Сервер - это авторитетная симуляция, определяющая фактические результаты. Сервер отправляет клиентам обновления каждые 50 мсек. Вместо интерполяции между двумя известными кадрами сервер экстраполирует позиции и т. Д. Для любых недостающих данных. Сервер знает, какая была последняя реальная позиция. Когда он получает обновление, следующий пакет, отправленный каждому из клиентов, включает обновленную информацию. Затем клиент должен получить эту информацию до достижения этого момента времени, и игроки реагируют на нее по мере ее появления, не видя никаких странных прыжков, потому что он никогда не отображал неправильную позицию.

Можно сделать так, чтобы клиент был авторитетным для некоторых вещей или чтобы клиент выступал в качестве авторитетного сервера. Ключевым моментом является определение степени доверия к клиенту.


Клиент должен регулярно отправлять обновления, скажем, каждые 50 мс. Это означает, что при «пике задержки» (задержка приема пакетов) в 500 мс либо все пакеты, отправленные в течение периода задержки, будут задержаны на аналогичную величину, либо пакеты будут получены не по порядку. Базовая сеть должна аккуратно обрабатывать эти задержки (отбрасывая пакеты, которые имеют слишком большую задержку, принудительно выполняя доставку пакетов и т. Д.). Конечным результатом является то, что при правильной обработке пакетов ожидаемые проблемы возникнуть не должны. Кроме того, отказ от получения явных местоположений символов от клиента и вместо этого явное исправление сервером клиента и получение только состояний управления от клиента предотвратит эту проблему.

person Matt    schedule 06.11.2009
comment
Я не понимаю, как ваша система может позаботиться об исправлении синхронизации, поскольку другие клиенты не знают точного положения соответствующего клиента. Если вы хотите, чтобы сервер вычислял позицию, а затем отправлял ее клиенту, просмотрите мои ответы Мэдсу. - person Tom; 06.11.2009
comment
Спасибо за разъяснение, но для меня это не имеет особого смысла, поскольку я уже использую время, когда сервер получает сообщение, а не время его обработки. В вашем примере все работает нормально, но, например, когда первый пакет задерживается, он будет показывать позицию 1 при времени 50 вместо 1. Затем, когда второй пакет не имеет задержки, он будет иметь позицию 3000 в момент времени 100. Это 50 разница во времени, которая может заставить его обнаружить это как мошенничество. Я не понимаю, как ваша система решает эту проблему, поскольку вы используете время, когда пакет получен сервером. - person Tom; 06.11.2009
comment
Для этого метода требуется базовая позиция и базовая отметка времени. Способ решения этой проблемы заключается в согласовании подключения. Сервер отправляет клиенту начальную позицию. Клиент отвечает точно такой же позицией, любое отклонение = обман. У вас есть разница во времени и разница в позициях. Покрывается задержка в обработке клиента. Сетевая задержка покрыта. Это не время приема-передачи, только когда сервер его получает. В вашем примере вы не использовали время, полученное сервером, вы использовали текущее время. Даже если это заняло 1/10 секунды, он мог перейти к следующему и нарушить значение времени. - person Matt; 06.11.2009
comment
Я до сих пор не понимаю, я никогда не говорил, что думал, что вы говорите о времени поездки туда и обратно. Это действительно время, когда сервер получает его, и, как я уже сказал, это может варьироваться. Поэтому, когда первое сообщение получено через 100 мс, а второе - через 25 мс, это вызовет проблемы. Я до сих пор не понимаю, где ваша система решает эту проблему. - person Tom; 07.11.2009