Cómo se creó el backend de un juego de piratas informáticos sobre la destrucción de un servidor



Continuamos contándoles cómo se organizó nuestra búsqueda láser con la destrucción del servidor. Comenzando en el artículo anterior sobre cómo resolver la búsqueda .



En total, el backend del juego contaba con 6 unidades arquitectónicas, que analizaremos en este artículo:



  1. Backend de entidades del juego que eran responsables de los mecanismos del juego
  2. Bus de intercambio de datos de backend y sitio en VPS
  3. Traductor de solicitudes de backend (elementos del juego) a arduino y hardware en el sitio
  4. Arduino, que estaba a cargo del control de relés, recibió comandos del traductor e hizo el trabajo real
  5. Dispositivos reales: ventilador, guirnaldas, lámparas de pie, etc.
  6. Frontend: el sitio Falcon en sí, desde el que los jugadores controlaban los dispositivos


Repasemos cada uno de ellos.



Backend de entidades del juego



El backend se implementó como una aplicación de arranque de primavera: tenía varios controladores de descanso, un punto final de websocket y servicios con lógica de juego.



Solo había tres controladores:



  • Megatron. La página actual de Megatron se envió a través de solicitudes GET: antes y después del encendido. El láser se disparó a través de una solicitud POST.
  • , . , ID .
  • , - .


El punto final de Websocket se utilizó para controlar dispositivos: lámparas, guirnaldas y letras. Se eligió para mostrar de forma sincronizada el estado actual del dispositivo a todos los jugadores: si está encendido o apagado, activo o no, qué color de la letra está ahora en la pared. Para complicar un poco la tarea de encender el láser, lanzamos autorización sobre la guirnalda y el láser con el mismo nombre de usuario y contraseña de administrador / administrador.



Los jugadores pueden probarlo encendiendo la guirnalda y haciendo lo mismo con el láser.



Hemos elegido un par de contraseña de inicio de sesión tan trivial para no atormentar a los jugadores con una selección innecesaria.



Para hacer la tarea un poco más interesante, se utilizó el ID de objeto de mongodb como identificadores de dispositivo en la sala.



ObjectId contiene una marca de tiempo: dos valores aleatorios, uno de los cuales se toma en función del identificador del dispositivo y el segundo en función del proceso pid que lo genera y el valor del contador. Quería hacer los identificadores generados a intervalos regulares y a partir de diferentes procesos pid, pero con un contador común, para que la selección del identificador del dispositivo láser fuera más interesante. Sin embargo, al final, todos empezaron con identificadores que solo difieren en el valor del contador. Quizás esto hizo que la etapa fuera demasiado simple y no requiriera un análisis de la estructura de los identificadores objectId.



Traductor de solicitudes de backend



Script de Python que se ocupa de los temporizadores y se traduce de las abstracciones del juego a un modelo físico. Por ejemplo, "enciende la lámpara de pie" → "enciende el relé N2".



El script se conectó a la cola de RabbitMQ y pasó las solicitudes de la cola a Arduino. También implementó la lógica del encendido paralelo de la luz: junto con algunos dispositivos, la luz se encendió en ellos, por ejemplo, cuando el Megatron se encendió inicialmente, se iluminó con luz de escenario. El diseño de iluminación para una escena cinematográfica completa es una historia separada sobre el gran trabajo de nuestro coproductor de proyecto y diseñador de producción Ilya Serov, y lo contaremos en una publicación separada.



El traductor también fue responsable de la lógica de poner en marcha la trituradora por temporizador y transmitir la imagen al televisor: el temporizador para poner en marcha la trituradora, el capibara gritando, el anuncio al final del juego.



Cómo se organizó la lógica de generar el token megatron



Tiro de prueba



Cada 25 segundos, se generaba una nueva ficha, que podía usarse para encender el láser durante 10 segundos a una potencia de 10/255. Enlace a github con código Megatron .



Luego, el láser se enfrió durante 1 minuto; durante este tiempo, no estuvo disponible y no aceptó nuevas solicitudes de disparo.



Este poder no fue suficiente para quemar la cuerda, pero cualquier jugador podía disparar desde Megatron y ver el rayo láser en acción.



Se utilizó el algoritmo de hash MD5 para generar el token. Y el esquema era MD5 de MD5 + contador + secreto para la ficha de combate y sin secreto para la prueba.



MD5 es una referencia a un proyecto comercial realizado por Pavel, nuestro backender. Hace solo un par de años, este proyecto usaba MD5, y cuando le dijo al arquitecto del proyecto que era un algoritmo de cifrado heredado, comenzaron a usar MD5 de MD5. Desde que decidimos hacer el proyecto Noob al máximo, se acordó de todo y decidió hacer una pequeña referencia.



Disparo de combate



El modo de combate de Megatron es 100% de potencia láser de 3W. Esto es suficiente por 2 minutos para quemar la cuerda que sostenía el peso para romper el acuario y llenar el servidor con agua.



Dejamos varios consejos sobre el github del proyecto: a saber, el código de generación de tokens, mediante el cual fue posible entender que los tokens de prueba y combate se generan en base a un indicador de contador. En el caso de la ficha de combate, además del valor del contador, también se usa la sal, que quedó casi completamente abandonada en el historial de cambios en esta esencia, a excepción de los dos últimos personajes.



Conociendo estos datos, fue posible iterar sobre los últimos 2 símbolos de sal y de hecho descubrir que para ello se utilizaron números de Lost, traducidos al sistema de 16 dígitos.



Luego, los jugadores tenían que capturar el valor del contador (analizando la ficha de prueba) y generar una ficha de combate utilizando el siguiente valor del contador y la sal seleccionada en el último paso.



El contador simplemente se incrementó con cada disparo de prueba y cada 25 segundos. No hemos escrito sobre esto en ninguna parte, debería haber sido una pequeña sorpresa en el juego.



Servicio de interacción con captcha



En el mundo del juego, este era el mismo captcha que tenía que cargarse para encender el ventilador y abrir un rotafolio con una pista. Había una computadora portátil con monitoreo de carga al lado de la cámara.







El servicio calculó qué mostrar en el monitoreo como la carga actual: temperatura y ventilador de la CPU. Las métricas se pasaron a la base de datos de la base de tiempo y se renderizaron en grafana.



Si en los últimos 5 segundos se recibieron más de 50 solicitudes de visualización de captcha, entonces la carga creció por corrección + un número aleatorio de pasos. El cálculo fue que se podía obtener el 100% de carga en dos minutos.



De hecho, había más lógica en el servicio de la que se mostró en el juego final: configuramos el monitor de tal manera que solo se veía la rotación del ventilador de la CPU.



Al comienzo de la búsqueda, querían dejar Grafana accesible desde el sitio web de Sokol. Pero también contenía métricas de springboot para el informe de la aplicación backend, que no tuvimos tiempo de limpiar, por lo que decidimos cerrar el acceso a él. Y con razón: al comienzo de la búsqueda, algunos jugadores adivinaron que la aplicación estaba escrita en el marco de Springboot e incluso desenterraron el nombre de algunos servicios.



Hosting y bus de datos



Una herramienta para transferir información desde el backend al sitio, el servidor VPS en el que se lanzó RabbitMQ.



El backend y el bus de datos se mantuvieron en nuestro VPS . Su potencia era comparable a la de la computadora que veías en la pantalla: un VPS de 2 núcleos con 2 gigabytes de RAM. La tarifa se tomó por recursos, ya que la carga máxima se planeó para solo unos días; esto es lo que hacen nuestros clientes, que planean cargar VPS por un corto tiempo. Luego resultó que la carga era más alta de lo que esperábamos y una tarifa fija sería más rentable. Cuando hagas una misión, elige las tarifas de la línea turbo .



Para proteger el servidor de DDoSa, usamos Cloudflare.



Cabe decir que el VPS resistió todo con gran éxito.



Arduino, que estaba a cargo del control de relés, recibió comandos del traductor e hizo el trabajo real



Este es más un tema para el próximo artículo sobre la parte de hardware del proyecto: el backend simplemente envió solicitudes para habilitar un relé específico. Dio la casualidad de que el backend conocía casi todas las entidades y las solicitudes de él parecían "habilitar esta entidad". Hicimos esto para las primeras pruebas del sitio (aún no habíamos recopilado todo el Arduino y los relés), al final lo dejamos así.



Interfaz



Rápidamente creamos el sitio en tilde, nos llevó un día hábil y nos ahorramos 30 mil del presupuesto.



Inicialmente, pensamos en exportar el sitio y agregar la lógica que nos faltaba, pero nos encontramos con términos de uso que nos prohibían hacer esto.



No estábamos preparados para violar la licencia, por lo que había dos opciones: inventarnos todo nosotros mismos o contactar a Tilda directamente, contarle el proyecto y pedir permiso para cambiar el código.



Elegimos la segunda opción y no solo nos recibieron a mitad de camino, sino que incluso nos dieron un año de cuenta comercial gratuita, por lo que estamos muy agradecidos. Fue muy vergonzoso mostrarles el diseño del sitio web de Sokol.



Como resultado, adjuntamos js-logic a la interfaz para enviar solicitudes a dispositivos elementales, cambiamos ligeramente los estilos de los botones para activar y desactivar elementos del juego.



Diseño del sitio



Historial de búsqueda, que vale un capítulo aparte.



Queríamos crear no solo un sitio anticuado, sino uno absolutamente nauseabundo que violara todas las reglas básicas de diseño. Al mismo tiempo, era importante preservar la credibilidad: tenía que no romper las historias de Otorrinolaringología, demostrar la pretenciosidad del autor y los jugadores tendrían que creer que tal sitio podría existir e incluso atraer clientes. ¡Y trajo! Mientras el juego estaba encendido, se nos pidió dos veces que creáramos sitios web.



Al principio, hice el diseño yo mismo, tratando de incluir más GIF y elementos brillantes. Pero mi esposo, un diseñador con 10 años de experiencia, miró por encima del hombro y lo descartó como "demasiado bueno". Para romper las reglas de diseño, necesita conocerlas.







Hay varias combinaciones de colores que provocan una persistente sensación de repugnancia: verde y rojo de igual jugosidad, gris y rosa, azul más marrón. Como resultado, nos decidimos por una combinación de rojo y verde como colores básicos, agregamos gifs con un gato y elegimos 3-4 fotos del propio Sokolov en el archivo fotográfico. Solo tenía unos pocos requisitos: un hombre de mediana edad, con un traje que no le quedaba bien, un par de tallas más grande y en la pose de "sesión de fotos profesional en el estudio". Para la prueba, se lo mostraron a sus amigos y preguntaron: "¿Qué te parece?"



En el proceso de desarrollo del diseño, mi esposo tuvo que acostarse cada media hora y comenzó a volar un helicóptero. Pasha intentó abrir la consola del desarrollador en la mayor parte de la pantalla, mientras estaba terminando la interfaz, se cuidó los ojos.



Dispositivos reales



Los ventiladores y las luces se montaron a través de relés de estado sólido para que no se encendieran a plena potencia de inmediato, de modo que la acumulación de energía ocurriera en paralelo con el monitoreo.



Pero hablaremos de esto en la próxima publicación, sobre la parte de hardware del juego y la construcción real del sitio.



¡Manténganse al tanto!



Otros artículos sobre la misión con la destrucción del servidor.








All Articles