Player.IO. Безопасность в онлайн играх

Мы уже говорили о безопасности в играх, но теперь настало время более подробно изучить этот вопрос.

Чаще всего внимание к безопасности в онлайн играх занижено по сравнению с такими аспектами разработки игры, как добавление новых фич или полировки игры. Но все же, наиболее важно, чтобы игра была надежной и защищенной, так как одно плохое игровое событие может испортить доверие игрока к игре. Например, вы хотели бы купить за реальные деньги какие-либо уникальные предметы в игре, где бегают одни читеры и хакеры? Я думаю, что вы не только не купили бы предметы, но и вообще не стали бы играть в такую игру. Таким образом мы должны быть уверены в том, что хакеры и читеры не смогут разрушить игровой процесс и испортить нашу работу.

Первый шаг, который обычно предпринимают в направлении защиты — это возможность сообщать игрокам о возможных читерах и хакерах. Но на этом сложно построить хорошую систему безопасности. Часто сообщения о хакерах и читерах сильно приувеличены, потому что порой не все игроки правильно понимают то, что происходит в игре, и иногда могут истолковать правильную игровую логику, как читерство. Такое случается, когда игрок не понимает игру должным образом и думает, что другой игрок его обманывает, когда он на самом деле делает все по правилам. С этим можно бороться явно, показывая игроку как играть, и разъяснять каждое игровое действие, результаты которого могут быть не достаточно понятными. То есть максимально информировать игроков о том, что происходит.

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

Flash уязвим для тех, кто собирается разобрать вашу программу на кусочки. Получение .swf файла с веб-страницы с последующим декомпилированием — занимает не более 5 минут. Так что если вы не приняли элементарные меры для защиты вашей программы от декомпиляции, то вы должны помнить, что любой желающий может взглянуть на исходный код вашей игры. И если это произойдет с сетевой игрой, то у хакеров будет вся необходимая информация, чтобы взломать игровой процесс, так как они уже будут знать, как ваша игра устроена внутри. Более того, они могут даже скомпилировать обратно модифицированный код и играть в переделанную игру, если, конечно, они знают, что делают.

Есть целый ряд продуктов, которые помогут защитить вашу игру от декомпиляции, методом шифрования, вот некоторые из них: Kindisoft, Amayeta и SWF Protection. Конечно, все это стоит много денег. Но здесь вы сами должны решить, нужна вам такая защита или нет.

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

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

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

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

  1. Сообщения отправляются и получаются нашим компьютером. Такие сообщения довольно легко обнаруживать, копировать и воспроизводить, зная какие программы для этого использовать.
  2. Применение альтернативных Flash клиентов. Такие типы атак включают шестнадцатеричное редактирование, декомпиляцию вашего приложения или увелечение скорости игры.

 

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

Давайте посмотрим на защиту нашего Flash приложения с точки зрения новичков. Если вы обеспечили защиту swf и уверены, что игра не может быть легко декомпилирована, то все равно следует позаботиться и о профилактике вероятных взломов клиента. Например, можно проверить не привышает ли частота кадров заданного максимума, что может быть реализовано сравнением с Date.getTime(). Это элементарная защита от ускорения игрового процесса. Так же следует сделать проверку важных переменных, например, проверка количества боеприпасов. Следует не допускать выхода количества патронов за заданный диапазон — это защита от правок значений через прямое изменение их в памяти. Такие подходы довольно эффективны при защите от простых читеров.

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

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

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

Во-первых, хакер может изменить содержание исходящих сообщений. Например, в сообщении, в котором содержится информация о «атака на 10 урона», он может изменить значение на «атака на 1000 урона».

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

К сожалению, мы не можем как-то противостоять хакеру, который занимается подделкой или блокировкой сообщений. Лучшее что мы можем сделать в этом случае — это максимально усложнить процесс извлечения информации из сообщений. То есть, проще говоря, мы можем шифровать данные или немного их видоизменять, добавляя какой-либо мусор во все данные с последующим удалением этого мусора на другой стороне — такого подхода, как правило, достаточно. Хакеры будут по-прежнему в состоянии изменить значения сообщений, но они не будут понимать, что получится в итоге. Например, для шифрования данных можно использовать алгоритм RSA... 

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

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

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

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

Будьте параноиками, но в пределах разумного!

Это вольный перевод статьи: «Building Flash Multiplayer Games — Security in multiplayer games»

Содержание

  1. Как создать онлайн игру? Анонс
  2. Player.IO. Введение
  3. Player.IO. Основы или первая онлайн игра
  4. Player.IO. Пошаговые игры
  5. Player.IO. Сетевые архитектуры
  6. Player.IO. Безопасность в онлайн играх
  7. Player.IO. Пример пошаговой игры
  8. Player.IO. Онлайн игры в реальном времени
  9. Player.IO. Синхронизация игроков
  10. Player.IO. Интерполяция или удивительный мир обмана
  11. Player.IO. Решение проблемы задержек
  12. Player.IO. Советы и рекомендации

 


Индикаторы: Уроки, Action Script 3
Постоянная ссылка

 

 

Отличный урок, спасибо!
Жду-недождусь практики по реал-тайм играм!

Ян
24 Октября 2012
— 01:06
#

@Ян, в следующей статье разберем на практике простую пошаговую игру и потом начинается информация уже по реалтаймовым играм :)

Ant.Karlov
24 Октября 2012
— 01:22
#

Отличная статья. Интересный Арт к уроку. Это специально к статье или к новому проекту :) ?

Иван
24 Октября 2012
— 08:39
#

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

Иван
24 Октября 2012
— 09:59
#

Простите за ошибки в тексте комментариев:)

Иван
24 Октября 2012
— 10:10
#

Жду практику :)

Wily
24 Октября 2012
— 12:27
#

Согласен с Иваном, для того чтобы обезопасить себя, желательно все вычисления проводить на стороне сервера. Например, та же атака - сервер получает информацию что игрок А хочет атаковать игрока Б, выясняет возможность этого(расстояние между ними, готовность героя совершить атаку и т.д. - в зависимости от проекта), рассчитвает нанесённый урон на основании своих зниний об оружии, умениях, броне оппонента, отправляет сообщения участникам о том что был нанесён урон.

Плюс не раскрыта тема SQL-инъекций которые являются сильной головной болью при работе клиент-сервер.

Честно говоря, не прочитал в статье ничего принципиально нового, но думаю многим кто не изучал вопрос, статья будет интересна. В любом случае, благодарю за проведённую работу, чем больше мануалов переведено на русский, тем приятнее работать)

Владимир
24 Октября 2012
— 16:09
#

@Иван, да, конечно же не следует отправлять сообщения с клиента типа как «атака с уроном в N единиц». Предполагаю, что в данной статье пример с уроном был только ради наглядного примера как можно подменить сообщения в свою пользу если они не зашифрованы. Даже если атака будет рассчитываться на сервере, то сообщения с важными данными все-равно будут отправляться с клиента и об их сохранности следует позаботится методами шифрования.

Ant.Karlov
24 Октября 2012
— 16:21
#

@Владимир, работу с БД у Player.IO я еще не смотрел, но мне кажется что там нет прямых запросов в SQL, поэтому тема SQL-иньекций в рамках этих уроков подниматься не будет. Данная статья конечно же ориентирована на новичков.

На основе своего опыта разработки сайтов, в плане SQL-иньекций могу посоветовать только одно: все данные которые попадают в БД должны фильтроваться на предмет спецсимволов, так же перед записью данных в БД следует приводить их к необходимому типу принудительно, что сводит к минимуму вероятность взлома БД путем модификации данных под запрос. Так же следует соблюдать синтаксис запросов (оборачивать значения в кавычки, ставить точки с запятыми в конце запросов и т.п.), что так же улучшает безопасность.

Ant.Karlov
24 Октября 2012
— 16:29
#

#Ant.Karlov Да, это позволяет избавится от большинства атак, собственно, приведение типа и проверка на спецсимволы является чуть ли не обязательной компонентой клиент-серверной архитектуры с использованием SQL. Даже если Player.IO не позволяет игроку взаимодействовать с БД напрямую, некоторые запросы(например, пара логин-пароль) всё равно должны идти в БД в чистом виде, что предполагает потенциальную уязвимость.

Кстати, спасибо за ссылку на RSA - почитал с интересом)

Владимир
24 Октября 2012
— 16:37
#

На тему SQL-инъекций. В PlayerIO используется система близкая к NoSQL (но не она) + все данные обрабатываются и проверяются, ничего криминального сделать не получится (ну или получится, но заморочиться придется конкретно так :) ).
И потенциальную угрозу имеют только один тип данных - String. Если хакер попытается что-то вставить в сообщение, например, координат пользователя, то сервер просто выдаст ошибку, так как мы обрабатываем именно конкретный тип данных (message.getInt(0)).

Izmy
24 Октября 2012
— 17:33
#

#Izmy Как раз пароль и логин всегда в String, мне кажется это самые опасные данные, поскольку их вводит сам пользователь.

Владимир
25 Октября 2012
— 09:50
#

Антон,
Спасибо большое за перевод уроков, давно хотел сделать мультиплеер игру, и вот решил попробовать топдаун шутер.

Ещё пока мало что готово, но бегать и стрелять уже можно - Epic Shooter

hanuman
28 Октября 2012
— 15:27
#

Кстати клиент делаю на AntHilll...:)

hanuman
28 Октября 2012
— 15:27
#

@hanuman, посмотрел демку, забавно выглядит. Правда управление плохо отзывается на действия игрока.

Ant.Karlov
29 Октября 2012
— 19:09
#

Приношу свои извинения за задержку с выходом уроков по Player.IO. Легкая простуда внесла свои коррективы. Следующий урок будет в ближайшие дни.

Ant.Karlov
29 Октября 2012
— 19:11
#

Поправляйтесь обязательно. И ждем новых уроков :)

Андрей
30 Октября 2012
— 01:21
#

Может глупость спрошу, но все же:
С точки зрения скорости, где лучше проводить вычисления - на стороне клиента или сервера?

Андрей
30 Октября 2012
— 02:41
#

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

Все сколь нибудь ценное - на сервере.

и.о. Капитан Очевидность
30 Октября 2012
— 03:28
#

2Ant.Karlov
Спасибо. Да, это результат высокого пинга до серверов PlayerIO в США. Надеюсь узнать как с этим бороться из последующих статей...:)

hanuman
30 Октября 2012
— 13:22
#

2hanuman
Я думаю в вашем можно сделать так:
1) клиент передает свои координаты на сервер и тут же, без ответа сервера, перемещает своего игрока (кружок).
2) на сервере мы проверяем не заходит ли кружек на стенку
3) после проверки отправляем всем другим игрокам, кроме того кого проверили, новые координаты.

Но на самом деле это очень-очень затратный метод - кучу информации надо передавать ежесекундно.
Я бы пошел по другому методу. Клиент передает ТОЛЬКО два события на кнопки - onKeyDown и onKeyUp. Нажали кнопку "W" - передает всем игрокам, что данный игрок идет вперед. Отжали кнопку - передаем всем, что данный игрок больше не идет вперед. Данный метод крайне положительно повлияет на трафик :)

Izmy
30 Октября 2012
— 19:25
#

@Izmy, сегодня будет рассмотрен пример пошаговой сетевой игры, а потом как раз пойдет информация на тему создания многопользовательских игр в реальном времени. Будем как раз рассматривать разные способы взаимодействия и синхронизации игровых клиентов.

Ant.Karlov
30 Октября 2012
— 21:44
#

не сочтиете за наглость
но хотелось бы знать, как вы Антон строите свой рабочий день?)
так сказать tips and trick удаленной работы дома )

бездельник
31 Октября 2012
— 01:30
#

2Izmy
В количестве трафика сейчас обмен клиент/сервер не сильно велик, при 4 игроках и условии что все стреляют около 2Кб/секунду. Но проблему пинга это не решает - задержка в 100мс даже уже заметна, а у кого пинг повыше играть становится не так интересно. Я на днях попробую возможно ли сделать свой сервер поближе. Если да, то это будет победа...:)

hanuman
31 Октября 2012
— 19:47
#

@hanuman, удаленность сервера сама по себе никак проблему не решит. Flash может использовать только медленный протокол TCP, поэтому если и удастся уменьшить задержку, то не более чем на 20-30мс, в лучшем случае (имхо).

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

Если даже вы сделаете сервер где-то в России, тем самым снизив задержки, то все равно может зайти пользователь с другого континента и все пропало :) Поэтому ваш подход к решению проблемы изначально не верен!

Ant.Karlov
31 Октября 2012
— 22:26
#

@бездельник, может быть напишу как-нибудь. Но сейчас мой рабочий день и вообще подход к работе — не самый хороший пример к подражанию! :)

Ant.Karlov
31 Октября 2012
— 22:30
#

2Ant.Karlov
Почему Вы думаете, что не решит проблему? Я поставил замер пинга для игроков и у некоторых даже сейчас был пинг 60мс, правда потом поднимался до 100. Если сделать сервер географически близко, то для игроков, у которых пинг будет до 75, задержка будет всего максимум 2 * пинг = 0.15 секунды. Это незначительная задержка, которая легко скрывается методами, которые Вы упомянули. В то же время если средний пинг 100-200 как сейчас, то задержку в 0,4 секунды уже сложнее скрыть и при разовых скачках пинга раздражения и игроков будет больше.

Насчёт игроков с другого континента, так эта проблема актуальна даже для AAA игр насколько я знаю. Поэтому во многих риалтайм проектах подобного типа игроки "сортируются" по комнатам по географической принадлежности. Но в любом случае спасибо за ответ.

А вообще честно говоря уже сейчас есть вещи которые очень ограничивают в серверной логике и в отношении к разработчикам в PlayerIO и я немного присматриваюсь к Photon Server

hanuman
1 Ноября 2012
— 16:18
#

@hanuman Мне PlayerIO хотя и интересен, я его не слишком рассматриваю в качестве реального инструмента... Всё же, при создании своей игры не очень хочется быть в зависимости от определённой платформы, контролируемой кем-либо другим. В случае с пошаговыми играми можно воспользоваться любым хостингом с поддержкой php+mySQL, но игры динамичные уже потребуют нормального сервера, который опять же, хотелось бы самостоятельно контролировать. Ну, или хотя бы отдать на откуп знакомому админу, оставив себе только написание серверного кода игры. Всё это, естественно, требует труда, знани, и зачастую денег, в то время как такие проекты как PlayerIO снимают все эти заботы с разработчика игры, тут уж приходится выбирать, что важнее. Я для себя пока решил не замахиваться на сложные задачи, и мультиплеерную составляющую реализовывать в доступных рамках, если вообще реализовывать. Не всё сразу) Бесплатный хостинг с бд вполне подходит для оттачивания и экспериментов)
Кстати, вопрос:

@Ant.Karlov а используемый в уроках Сишный код работает только с сервисом PlayerIO на их серверах, или описанные приёмы можно реализовать и на своём сервере?

Владимир
2 Ноября 2012
— 11:30
#

@hanuman, перенос сервера в Россию — это лечение проблемы. Но в случае с онлайн играми лечение проблемы задержек — это бесполезная трата времени и средств, надо бороться с симптомами, то есть максимально работать над тем, чтобы скрыть задержки.

Вся проблема заключается в том, что ваше решение будет работать хорошо ровно до тех пор пока не зайдет игрок с другого континента. Да что там с континента, Россия настолько велика, что игрок из Владивостока может испортить картинку плавной игры которая живет на сервере в Москве. Более того, не обязательно чтобы игрок был далеко от сервера, достаточно даже медленного соединения с Интернет, чтобы «сунуть ложечку дегтя в бочку меда». В дальнейших статьях как раз рассказывается о том, в чем заключается «магия» сокрытия всех этих проблем чтобы игроки верили в справедливость и наслаждались играми, хотя при этом полно проблем с задержками и нет никакой справедливости :)

Распределение серверов по континентам — это тоже конечно выход, но не в нашем случае. Чтобы заводить сервера для разных континентов, а еще лучше для разных стран — нужно иметь такой продукт где такой подход целесообразен. А в вашем случае, следует поработать над «магией» сокрытия проблем с задержками ;)

Надеюсь убедил.

Ant.Karlov
2 Ноября 2012
— 23:59
#

@Владимир, C# код который мы пишем на сервере с использованием Player.IO — это лишь наша логика игры. Если покопаться в исходниках шаблона для сервера то можно понять, что это некий API который работает с их серверами (я правда не копался). То есть логика игры написанная на сервере Player.IO с использованием C# может быть легко перенесена на любой сервер, но при этом, скорее всего придется, либо писать свой API для своего сервера, либо портироваться под уже существующие серверные решения.

Ant.Karlov
3 Ноября 2012
— 00:04
#

Не забываем настраивать дмп, на создание бакапов баз данных.

Kain
16 Ноября 2012
— 11:20
#