Залізо проекту: як ми будували кімнату з хакерським квестом

Залізо проекту: як ми будували кімнату з хакерським квестом
Пару тижнів тому ми провели онлайн-квест для хакерів: побудували кімнату, яку заповнили розумними пристроями та запустили з неї YouTube-трансляцію Гравці могли керувати IoT-девайсами із сайту гри; метою було знайти заховану в кімнаті зброю (потужну лазерну указку), хакнути її та влаштувати в кімнаті коротке замикання.

Щоб додати гостросюжетності, ми поставили в кімнаті шредер, який завантажили 200 000 рублів: шредер з'їдав по купюрі на годину. Вигравши гру, можна було зупинити шредер і забрати всі гроші, що залишилися.

Ми вже розповідали проходження гри, а також як був зроблений бекенд проекту. Настав час розповісти про хардвар і як він збирався.


Було дуже багато запитів показати момент прибирання кімнати – показуємо, як ми її розуміємо.

Архітектура заліза: керування кімнатою

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

Згадуючи старий анекдот "The S in IoT stands for Security" ("Літера S в абревіатурі IoT позначає Security") ми прийняли рішення, що цього разу гравці за сценарієм гри взаємодіють тільки з фронтендом та бекендом сайту, але не отримують можливості дістатися безпосередньо до заліза.

Це було зроблено з міркувань безпеки та видовищності того, що відбувається на екрані: за безпосереднього доступу гравців до заліза, було б значно складніше ізолювати безпечні та потенційно небезпечні дії, наприклад, прискорене прокручування шредера або управління піротехнікою.

Перед початком проектування у нас сформулювалися кілька принципів керування ігровими пристроями, які стали базою конструкції:

Не використовувати бездротові рішення

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

Не використовувати якісь спеціальні пристрої від розумного будинку

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

Крім того, потрібно було придумати пристрої, якими буде явно видно, що саме гравці змінюють його стан: включили/вимкнули або проставили конкретне світло на літерах СОКОЛ.

Ми зібрали всі елементи із загальнодоступного заліза, яке можна купити у звичайних магазинах радіодеталей: між доставкою піци та дієтичної кіл, на майданчик постійно приїжджали кур'єри Чіп та Діп та Леруа.

Вибір зібрати все самим спрощував налагодження, масштабованість, проте вимагав більшої акуратності при монтажі.

Все реле та арудино не повинно бути видно у кадрі

Ми вирішили звести всі керовані елементи в одне місце і сховати за кадром, щоб мати можливість контролювати працездатність і, якщо знадобиться, акуратно проповзти поза зоною видимості камери і замінити блок, що вийшов з ладу.

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

У результаті у нас вийшов фактично один розумний пристрій: він отримував від бекенда стан кожної своєї частини та змінював його відповідною командою.

З точки зору апаратної реалізації цей пристрій керував 6 елементами:

  1. Декілька настільних ламп, вони мають стан вкл/викл і управляються гравцями
  2. Літери на стіні можуть змінювати свій колір за командою гравців.
  3. Вентилятори, що крутяться та відкривають фліпчарт при навантаженні на сервер
  4. Лазер, який керується через ШІМ
  5. Шредер, який зжирав гроші за розкладом
  6. Дим-машина, яка спрацьовувала перед кожним пострілом лазера


Тестуємо дим-машину разом із лазером

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

Що собою представляло цей розумний пристрій

Залізо проекту: як ми будували кімнату з хакерським квестом

Всю дорогу Юра, наш хардварник, намагався не ускладнювати і вигадати найпростіше, мінімалістичне рішення з можливих.

Передбачалося, що на VPS крутитиметься просто скрипт, який отримує json зі станом пристроїв і пересилає його на підключену ардуїнку usb.

До портів підключалися:

  • 16 звичайних реле (саме вони видавали те клацання, яке було чути на відео. В основному ми вибрали їх через цей звук)
  • 4 твердотільних реле для керування каналів з ШІМ, наприклад вентиляторів,
  • окремий ШІМ вихід для лазера
  • висновок, що формує сигнал на світлодіодну стрічку

Ось приклад json-команди, яка надходила до реле від сервера

{"power":false,"speed":0,"period":null,"deviceIdentifier":"FAN"}

І це приклад функції, з допомогою якої команда потрапляла на арудино

def callback(ch, method, properties, body):    
request = json.loads(body.decode("utf-8"))    
print(request, end="n")     
send_to_serial(body)

Щоб відстежити момент, коли лазер нарешті перепалить мотузку та гиря полетить на акваріум, ми зробили невелику кнопку, яка спрацьовувала на падіння гирі та давала сигнал системі.

Залізо проекту: як ми будували кімнату з хакерським квестом
Кнопка-моніторинг руху гирі

При цьому сигналі повинні були спалахнути димові шашки, зроблені з кульок для пінг-понгу. Ми вклали 4 димовухи прямо в корпус сервера і підвели до них ніхромову нитку, яка мала розжаритися і спрацювати як запал.

Залізо проекту: як ми будували кімнату з хакерським квестом
Корпус з димовими шашками та китайською гірляндою

Залізо проекту: як ми будували кімнату з хакерським квестом

Ардуїно

На ардуїнці за первісним задумом відбувалося дві дії.

Перше - при отриманні нового запиту, запит парсився за допомогою бібліотеки ArduinoJson. Далі кожному керованому пристрою зіставлялися дві властивості:

  • стан живлення «ввімкнено» або «вимкнено» (стандартний стан)
  • період, на який пристрій увімкнено - час у мікросекундах від старту плати, коли вже час її вимикати, тобто приводити стан до стандартного

Останнім часом ставилося при отриманні відповідного параметра JSON, однак його можна було і не передавати, тоді значення встановлювалося в 0 і обнулення не відбувалося.

Друга дія, яку робила ардуїнка кожен цикл — це актуалізація станів, тобто перевірка, чи немає необхідності щось увімкнути, чи не настав час вимикати будь-який пристрій.

Лазерна указка - цей Мегатрон 3000

Залізо проекту: як ми будували кімнату з хакерським квестом

Це звичайний лазерний модуль для різання та маркування LSMVR450-3000MF 3000мВт 450нм з ручним фокусуванням.

Літери Сокіл

Зроблено дуже просто — ми просто скопіювали літери з логотипу, вирізали їх із картону, а потім обклеїли led-стрічкою. При цьому довелося спаювати шматки стрічки між собою, по 4 контакти на кожному шві, але результат того коштував. Наш бекендер Паша показав чудеса вмілості, зробивши це менше ніж за кілька годин.

Перші тести iot-пристрою та допилювання

Ми зробили перші тести і заразом нам під'їхали нові завдання. Справа в тому, що в середині процесу до команди приєднався справжній кінопродюсер і оператор із ВДІКу Ілля Сєров — він збудував кадр, додав додаткове кіношне освітлення і трохи змінив сценарій гри, щоб сюжет виходив більш емоційним, а картинка драматичнішою і театральнішою.

Це суттєво збільшило якість, але з'явилися елементи, які теж знадобилося підключати до реле та прописувати алгоритм роботи.

Іншою проблемою виявився лазер: ми провели кілька експериментів із різними типами мотузки та лазерами різної потужності. Для тесту ми просто вертикально підвішували вантаж на мотузці.

При запуску з тестовим токеном регульована потужність через шим становила менше 10% і мотузку не пошкоджувала навіть при тривалій експозиції.

Для бойового режиму лазер розфокусували приблизно до плями діаметром 10 мм і він впевнено перепалював мотузку з вантажем з відстані близько метра.

Залізо проекту: як ми будували кімнату з хакерським квестом
Так лазер спрацьовував добре на тестах

Коли ми вже почали тестувати все прямо в кімнаті на підвішеній гирі, виявилося, що надійно закріпити лазер не так просто. Потім, коли мотузка горить — вона плавиться, розтягується і зміщується з-під початкового фокусу.

Залізо проекту: як ми будували кімнату з хакерським квестом
А ось так він уже не працював: мотузка зміщувалась

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

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

Залізо проекту: як ми будували кімнату з хакерським квестом
Нитка, яка в результаті перепалювала мотузку за кадром

Таким чином з'явилося третє завдання, яке вирішувала ардуїнка — відпрацювати послідовності, пов'язані з виконанням цих команд.

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

Але на тестовому прогоні Ілля переглянув сцену і запропонував на найбільшому екрані показувати ігровий баланс: скільки грошей ще залишилося, скільки з'їдено та зворотний відлік до наступного запуску шредера.

Ардуїно ми зав'язали на поточний час: кожну повну годину запускався шредер. Картинка на телевізор видавалася за допомогою розпберрі, яка на той момент вже отримувала з сервера запити та пересилала їх на виконання в ардуїнку. Картинки з грошовими показниками малювались за допомогою виклику консольної утиліти fim приблизно так

image = subprocess.Popen(["fim", "-q", "-r", "1920×1080", fim_str]), где fim_str

І формувалася з потрібної суми чи часу.

Картинки ми згенерували заздалегідь: просто взяли готове відео з таймером та експортували 200 картинок.

Ось така механіка була запрограмована у хресті. До моменту, як запустився фінальний відлік, ми всі виїхали на майданчик, озброїлися вогнегасниками і сіли чекати на пожежу (яка палала тільки в дискорді).

Як зробити трансляцію, яка працює тиждень: вибір камери

Для квесту нам потрібна була безперервна трансляція на Ютубі протягом 7 днів — саме стільки ми закладали як максимальну тривалість гри. Було дві речі, які нам могли завадити:

  1. Перегрів камери від безперервної роботи
  2. Обрив інтернету

Камера мала віддавати картинку як мінімум Full HD, щоб грати і спостерігати за кімнатою було комфортно.

Спочатку ми дивилися у бік веб-камер, які випускають для стримерів. Ми різали бюджет, тож купувати камеру не хотілося, а в оренду, як виявилось, їх не дають. У цей же момент ми дивом знайшли камеру Xbox Kinect, що лежала у мене вдома, поставили в кімнаті і запустили тестову трансляцію на тиждень.

Камера справлялася нормально і не перегрівалася, але Ілля майже одразу помітив, що в ній не вистачає налаштувань, зокрема, не можна виставити експозицію.

Ілля прагнув наблизити вид трансляції до стандартів кіно-відео виробництва: передавати світлову сцену, що динамічно змінюється, з яскравими джерелами світла, затемненим фоном і предметами в кадрі. При цьому хотілося зберегти опрацювання зображення як у світлі так і в тінях, з мінімальним цифровим шумом.

Тому, хоч кінект і показав себе надійним при тестах і йому не була потрібна плата відеозахоплення (ще одна точка відмови), від нього ми вирішили відмовитися. Після трьох днів тестів різних камер, Ілля вибрав Sony FDR-AX53 - невеликий надійний камкордер, бюджетний в оренді, але при цьому має достатню надійність і образотворчі характеристики.

Ми орендували камеру, включили її на тиждень у зв'язці з платою відеозахоплення і зрозуміли, що з нею можемо розраховувати на безперервну трансляцію на протязі всього квесту.

Робимо кіно: постановка сцени та світла

Робота над освітленням вимагала певної витонченості, нам потрібно мінімальними засобами вибудувати світлову партитуру:

1. Підсвічування предметів, коли їх знаходять гравці (лазер, гиря), а також постійне світло на шредер. Тут використовувалися dedolight 150 - надійні та компактні освітлювальні кіноприлади з низьковольтними галогенними лампами, що дозволяють акцентно сфокусувати промінь на конкретному предметі, не зачіпаючи фон та інші предмети.

2. Практичне ігрове світло - настільна лампа, торшер, зірка, гірлянда. Все практичне світло було гармонійно розподілене в кадрі, щоб висвітлювати свою область зображення, всередині стояли led лампи з колірною температурою 3200К, лампа в торшері була закрита червоним фолієвим фільтром Rosco, для створення незвичайного колірного акценту-підказки.

Залізо проекту: як ми будували кімнату з хакерським квестом
Я у мами інженер або запуск завтра

Як ми резервували інтернет та електрику

До питання відмови стійкості підійшли майже як у дата-центрі: вирішили не відступати від основних принципів і зарезервували за звичною схемою N+1.

Якщо на ютубі трансляція припиняється, це означає, що заново приєднатися за тим самим посиланням і продовжити стриму вже неможливо. Це був критичний момент, до того ж кімната була у звичайному офісі.

Для цього ми використовували роутер на базі OpenWRT та пакет mwan3. Він автоматично тестував кожні 5 секунд доступність каналу і у разі обриву перемикався на резервний модем з Yota. У результаті перемикання на резервний канал відбувалося менше, ніж за хвилину.
Залізо проекту: як ми будували кімнату з хакерським квестом
Також не менш важливо було виключити перебої з електрикою, адже навіть короткочасний стрибок напруги викликав би перезавантаження всіх комп'ютерів.

Тому ми взяли безперебійник ippon innova g2 3000, який резервував би всі ігрові пристрої: сумарна споживана потужність нашої системи була близько 300 Ватт. Його вистачило б на 75 хвилин, цілком достатньо для наших цілей.

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

Подяки

  • усій команді РУВДС, яка вигадувала та реалізовувала гру.
  • Окремо адмінам RUVDS, за те, що стежили за роботою серваків, навантаження було прийнятним і все працювало штатно у звичайному режимі.
  • Найкращому босу ntsaplin за те, що у відповідь на дзвінок є ідея: ми візьмемо сервер, на нього поставимо акваріум, а над ним підвісимо гирю, бум, бах, все залило водою, коротке замикання, пожежа! він завжди впевнено каже «робіть!»
  • Дякуємо Видавництво Тільда та окремо Михайлу Карпову за те, що він не просто пішов назустріч та дозволив порушити Terms of use, але навіть подарували нам бізнес-аккаунт на рік, коли ми розповіли про проект.
  • Іллі Сєрову S_ILya за те, що він приєднався і став співпродюсером проекту, готовим півночі повзати, приклеюючи світлодіодну стрічку, шукати технічні рішення та зробити все, щоб у нас вийшло справжнє кіно.
  • zhovner за те, що завжди був готовий урятувати ситуацію, коли інші розводили руками, борщик, моральну підтримку та розмови до ранку.
  • самат за те, що пов'язав нас із найкращим пентестером країни, який проконсультував нас і допоміг із завданнями.
  • daniemilk за крутий відеопродакшен всіх роликів.
  • delfphe за тверду руку та готовність працювати до останнього.
  • Ну Dodo Pizza Engineering за майже завжди теплу піцу.

І найбільша подяка - гравцям за всі емоції, які ми пережили, поки ви дві доби штурмували квест без сну і навіть відклавши роботу.

Інші статті про квест зі знищенням сервера

Залізо проекту: як ми будували кімнату з хакерським квестом

Джерело: habr.com

Додати коментар або відгук