Как мы перебанили обычных игроков и заDDoSили свои сервера: практическое руководство

в 9:30, , рубрики: fail, Блог компании Pixonic, разработка, разработка игр, Управление продуктом, управление разработкой, факапы

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

Как мы перебанили обычных игроков и заDDoSили свои сервера: практическое руководство - 1

Проиграл — получи бан

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

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

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

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

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

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

Вот тут-то нас и накрыло.

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

Всех, конечно, разбанили и даже компенсацию выплатили, но ситуация так себе, не позитивная точно.

Как мы перебанили обычных игроков и заDDoSили свои сервера: практическое руководство - 2

Как устроить самому себе DDoS

Уже писали про эволюцию нашей инфраструктуры серверов, а сейчас вспомнили один случай того времени.

В конце 2015 года состоялся релиз долгожданной фичи в War Robots — кланов. Когда вышло обновление (а это было поздно вечером), мы открыли шампанское и все было бы хорошо. Но радоваться пришлось недолго — серверам внезапно стало плохо. Оказалось, что мы собственными руками устроили себе DDoS-атаку.

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

Той же ночью мы запилили флажок (шампанское мы при этом закрыть не успели), который контролировался с профиль-сервера — он полностью блокировал работу Hangar Client API. Игрокам, которые уже вступили в кланы, мы этот флажок оставили включенным, то есть у них все работало, потому что их количество было недостаточно, чтобы заDDoSить сервера.

В итоге мы начали корректно обрабатывать ответы сервера в игре, а в случае ошибки — увеличивать таймаут на повтор запроса.

«Бесплатный» рейтинг

Отдельная история — это когда некачественная реализация встречает человеческий фактор. Только теперь никого не банили, а наоборот раздавали рейтинг налево и направо. Короче, как-то ночью наш мониторинг (а мы мониторим вообще всё) зафиксировал слишком быстрый рост рейтинга игроков.

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

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

Бесценный приз

С опечаткой был еще один факап, но куда более серьезный.

Как-то на Хэллоуин мы запускали новую гачу — лотерею. Если кто не знает, гача — это механика получения предмета из нескольких разных случайным образом. В лотерее у игрока был ограниченный видимый набор призов разной ценности. За каждое открытие игрок получал 1 приз, этот приз вынимался из набора, а цена открытия с каждым разом возрастала. Таким образом игрок мог гарантированно скупить все призы лотереи, а счастливчики вынимали самые ценные призы на первых открытиях (и соответственно получали их очень дёшево).

В общем, потом и кровью мы запилили фичу к ивенту, протестили, выложили. Запускаем, обновляем графики… УРА! Они рванули вверх!.. И одновременно на нас обрушиваются тонны негатива в комьюнити, что мы якобы обманываем своих игроков.

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

В интерфейсе лотерии указана стоимость текущего открытия (та, которая возрастала с каждым разом), например, PRICE: 100 Gold. Специально выделена на скриншоте:

Как мы перебанили обычных игроков и заDDoSили свои сервера: практическое руководство - 3

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

Но почему-то переводчики при пруфриде решили заменить «C» на «Z»! Т.е. «Price» (цена за участие в лотерее) внезапно превратилась в «Prize» (приз). И игроки рефлекторно жали кнопку, пока не тратили ВСЮ харду. Ну а что, «приз» же увеличивается с каждой покупкой.

Как мы перебанили обычных игроков и заDDoSили свои сервера: практическое руководство - 4

И так было на 18 языках. При этом «локали» у нас были на клиенте, поэтому исправить одну букву можно было только через хотфикс.

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

Самое время вводить хештег #косякинапроде

Автор: azazelis

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js