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

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

Всего у бекенда игры было 6 архитектурных единиц, которые мы и разберём в этой статье:

  1. Бекенд игровых сущностей, которые отвечали за игровые механизмы
  2. Шина обмена данных бекенда и площадки на VPS
  3. Транслятор из запросов бекенда (игровых элементов) на ардуино и железо на площадке
  4. Ардуино, которая занималась управлением релешками, получала команды с транслятора и делала фактическую работу
  5. Фактические устройства: вентилятор, гирлянды, торшеры и прочее
  6. Фронтенд — сам сайт Сокола, с которого игроки управляли устройствами

Давайте пройдёмся по каждой из них.

Бекенд игровых сущностей

Бекенд был реализован, как spring boot-приложение: оно имело несколько rest-контроллеров, websocket endpoint и сервисы с игровой логикой.

Контроллеров было всего три:

  • Мегатрон. Через GET-запросы отдавалась актуальная страница Мегатрона: до и после включения питания. Через POST-запрос лазер стрелял.
  • Мапинг тильдовских страниц, чтобы они отдавались по имени страницы. У тильды на экспорт выдаются страницы не с оригинальными названиями, а внутренним ID и информацией по соответствию.
  • Контроллер для капчи, чтобы отдавать псевдо-высокозагружающую сервер капчу.

Websocket endpoint использовался для управления гаджетами: лампами, гирляндой и буквами. Его выбрали, чтобы синхронно отображать всем игрокам текущий статус устройства: включено оно или выключено, активно или нет, какой цвет буквы сейчас горит на стене. Для того чтобы чуть-чуть усложнить задачу включения лазера, мы накинули авторизацию на гирлянду и лазер с одинаковым логином и пароль admin/admin.

Игроки могли протестировать его на включении гирлянды и повторить то же самое на лазере.

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

Чтобы сделать задачу чуть поинтересней, в качестве идентификаторов устройств в комнате использовались object ID из mongodb.

ObjectId содержит в себе timestamp: два случайных значения, одно из которых берётся на основании идентификатора устройства, а второе на основании pid-процесса, который генерирует его и значение счётчика. Хотелось сделать идентификаторы сгенерированными через равные промежутки времени и с разными pid-процессов, но общим счётчиком, чтобы подбор идентификатора устройства лазера был интереснее. Однако в итоге все запустились с идентификаторами, различающимися только в значении счётчика. Возможно, это сделало этап слишком простым и не требующим анализа структуры идентификаторов objectId.

Транслятор из запросов бекенда

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

Скрипт подключался к очереди RabbitMQ и передавал запросы из очереди на Ардуино. Также на нём была реализована логика параллельного включения света: вместе с некоторыми устройствами на них включался свет, например, при первичной подаче питания на Мегатрон, он подсвечивался сценическим светом. Дизайн света для кинематографичности всей сцены — отдельная история про большую работу нашего сопродюсера проекта и художника-постановщика Ильи Серова, и про неё мы расскажем в отдельном посте.

Транслятор также отвечал за логику запуска шредера по таймеру и передачу изображения на телевизор: таймер запуска шредера, кричащая капибара, рекламный ролик в конце игры.

Как была устроена логика генерации токена мегатрона

Тестовый выстрел

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

Затем лазер охлаждался 1 минуту — в это время он был недоступен и не принимал новые запросы на выстрел.

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

Для генерации токена использовался алгоритм хеширования MD5. И схема получалась MD5 от MD5 + счётчик + секрет для боевого токена и без секрета для тестового.

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

Боевой выстрел

Боевой режим Мегатрона — это 100% мощность лазера в 3 Вт. Этого вполне достаточно на 2 минуты, чтобы пережечь верёвку, которая держала гирю, чтобы разбить аквариум и залить сервер водой.

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

Зная эти данные, можно было перебрать 2 последних символа соли и фактически выяснить, что для неё использовались числа из Lost, переведённые в 16-ичную систему.

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

Счётчик просто инкрементировался при каждом тестовом выстреле и каждые 25 секунд. Об этом мы нигде не писали, это должно было быть небольшой игровой неожиданностью.

Сервис взаимодействия с капчей

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

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

Сервис подсчитывал, что отображать в мониторинге как текущую нагрузку: температуру и CPU Fan. Метрики передавались в timebase database и отрисовывались графаной.

Если за последнее 5 секунд поступало более 50 запросов на отображение капчи, то нагрузка росла на фикс + рандомное количество шагов. Расчёт был на то, чтобы 100% нагрузку можно было получить за две минуты.

В самом деле логики в сервисе было больше, чем отобразилось в конечной игре: мы поставили монитор таким образом, что было видно только вращение CPU Fan.

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

Хостинг и шина обмена данных

Инструмент передачи информации с бекенда на площадку, VPS-сервер на котором было запущено RabbitMQ.

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

Чтобы защитить сервер от DDoSa, мы использовали Cloudflare.

Стоит сказать, что VPS с честью выдержала всё.

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

Это больше тема следующей статью про хардварную часть проекта: бекенд просто присылал запросы включить конкретное реле. Так вышло, что бекенд знал почти все сущности и запросы с него, выглядели как «включи эту сущность». Мы делали это для раннего тестирования площадки (пока ещё не собрали все Ардуино и реле), в итоге так всё и оставили.

Фронтенд

Сайт мы быстро создали на тильде, это заняло один рабочий день и сэкономило нам тысяч 30 бюджета.

Изначально мы думали просто экспортнуть сайт и накинуть нехватающую нам логику, но нарвались на terms of use, которые нам это запрещали.

Мы не были готовы нарушать лицензию, поэтому было два варианта: сверстать всё самим или напрямую связаться с Тильдой, рассказать о проекте и попросить разрешения менять код.

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

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

Дизайн сайта

История поисков, которая стоит отдельной главы.

Мы хотели создать не просто старомодный сайт, а абсолютно тошнотворный, нарушающий все базовые правила дизайна. При этом было важно сохранить правдоподобность: он должен был не ломать ЛОР истории, демонстрировать претенциозность автора и игроки должны были бы поверить в то, что такой сайт может существовать и даже приводить клиентов. И привёл! Пока шла игра, нам дважды обращались за созданием сайтов.

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

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

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

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

Фактические устройства

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

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

Stay tuned!

Остальные статьи про квест с уничтожением сервера

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

Источник: habr.com