Autenticación para un juego multijugador a través de sockets

11

Estoy implementando un protocolo binario personalizado para un nuevo juego multijugador en el que estoy trabajando. Es un juego de estrategia por turnos, por lo que el tiempo realmente no importa. Actualmente tengo completa la parte básica de sincronización de datos del sistema, y ​​me preguntaba cómo el inicio / cierre de sesión del usuario y el cifrado generalmente se realizan para juegos MMORPG o similares.

  • ¿Me puede recomendar un esquema para la transmisión de contraseña segura / secreta durante el inicio de sesión? (¿Intercambio de llaves Diffie-Hellman?)
  • ¿Cómo implemento un cifrado seguro para los paquetes de datos? (¿AES de 128 bits? ... o cualquier esquema al que esta publicación se refiera como "cifrado más fuerte de lo que es probable que descifre")
  • ¿Existen esquemas de formato de datagramas que ayudan a fortalecer el servidor del juego para reproducir ataques, paquetes de datos no válidos y similares?
Robinicks
fuente

Respuestas:

15

Respuestas

  • SRP : contraseña remota segura: se basa en Diffie-Hellman. La idea es que puede hacer una verificación mutua de la contraseña sin tener que transferir la contraseña o la información que pueda usarse para obtenerla. A pesar de que es seguro a través del cable, aún debe modificar y eliminar sus contraseñas, ya que su servidor nunca debe almacenarlas en texto sin formato .
  • La ventaja de SRP es que una vez que se completa, también le brinda una clave de cifrado negociada mutuamente que un atacante no podría deducir dados los datos que ha transferido. Esto significa que puede utilizar un algoritmo de cifrado simétrico (como AES) una vez que el usuario se autentica.
  • Suponiendo que está utilizando UDP con su propia implementación confiable / ordenada (orientada a la conexión), cifre toda la carga de reproducción UDP, incluido su 'número de secuencia de paquete'. Si su sistema está diseñado correctamente, rechazará automáticamente los mensajes reproducidos y un intruso no podrá cambiar el número de secuencia del paquete porque está encriptado (por lo tanto, es posible una reproducción, pero se ignorará automáticamente).

Pensamientos

¿Debería ser segura su autenticación? Absolutamente. No haga concesiones en términos de seguridad cuando se cuestione una contraseña. Por lo tanto, definitivamente debería considerar la primera viñeta en mi respuesta.

¿Deberían estar seguros sus datos? Solo si se trata de una compra / micro-transacción en el juego, y entonces, ¿por qué no usar algo probado y verdadero como HTTPS? Cifrar el tráfico de tu juego probablemente no sea una solución viable por las siguientes razones:

  • Es una paranoia completa.
  • Agregará una sobrecarga de tiempo de CPU en su servidor, a menos que pueda comprar módulos de cifrado de hardware (costosos).
  • No importa cuánta seguridad proporcione para sus datos a través del cable: alguien podría secuestrar el proceso del cliente e interceptar mensajes el momento antes de que se cifren y se envíen. Esto no es solo una posibilidad, sino que es infinitamente más posible, ya que es mucho más fácil inyectar código en comparación con los paquetes de interceptación. Si está haciendo esto para la prevención de trampas, está perdiendo su tiempo por completo.
    • En términos de seguridad de contraseña, lamentablemente no hay nada que pueda hacer razonablemente sobre un sistema secuestrado, el cliente se ha vuelto hostil. Los dongles de Blizzards WoW están diseñados para lidiar con esto, pero no estoy seguro de cuán seguro es eso (especialmente si lo dejas enchufado).

Por favor, si está encriptando para la prevención de trampas, abandónelo. Te vas a quedar corto: te di la información en caso de que no lo estés. Recuerde que puede cifrar selectivamente los paquetes por el primer byte en el paquete e indicar si el resto está cifrado: aunque, una vez más, me apegaría a HTTPS si necesita hacer cosas como transacciones con tarjeta de crédito: son extremadamente infrecuentes y HTTPS está diseñado por expertos, a diferencia de algo que usted o yo diseñamos.

Dicho todo esto, Blizzard encripta su tráfico de WoW. La razón principal por la que esto se rompió es porque alguien, que probablemente sea un completo aficionado, decidió que probaría con un algoritmo de encriptación local; esto funcionó muy bien . Incluso si utiliza algoritmos estándar de la industria, existe una buena posibilidad de que alguien realice una ingeniería inversa de su código y lo simule; una vez que el cliente ingresa su contraseña, no se sabe si un sistema no compatible está conectado.

Jonathan Dickinson
fuente
2
+1 por decir que cifrar paquetes de datos para la prevención de trampas es inútil. OP: verifique todo lo que recibe del cliente, ejecute controles de cordura, verifique dos veces si la acción solicitada por el cliente es posible, verifique los rangos de armas, la velocidad de movimiento, etc. pero no pierda el tiempo asegurando a su cliente, ya que será pirateado si tu juego lo vale. Algunas compañías de MMO encriptan y ofuscan a sus clientes / protocolos, pero no es para evitar trampas, sino para que sea más difícil, por ejemplo, para los creadores de bots obtener buenos resultados, e incluso esto lo hacen equipos de expertos dedicados.
Galaad
1
Una pequeña objeción acerca de su tercera respuesta: solo cifrar los paquetes puede no ser suficiente para evitar la manipulación, ya que muchos esquemas de cifrado son al menos algo maleables . Para proteger la integridad del mensaje, necesita un modo de cifrado MAC o autenticado .
Ilmari Karonen
+1 Gracias por una respuesta muy completa. Buscando implementar SRP ahora mismo. ¿Cuáles son sus recomendaciones con respecto a la función hash utilizada para las contraseñas? MD5? ¿Cómo sería el protocolo OTR (Off the Record) para tal caso de uso? ¿funcionaría bien para auth / crypto en lugar de SRP? En caso de que use SRP, ¿necesitaría usar uno de los siguientes modos de "encriptación autenticada"? (OCB 2.0, Key Wrap, CCM, EAX, Encrypt-then-MAC y GCM)
Robinicks
1
@Jenko utiliza la familia de algoritmos SHA (probablemente SHA1); en estos días, debe evitar MD5. OTR realmente no es algo que debería mirar: no está diseñado para ser seguro / oscuro (de hecho, está diseñado para que alguien pueda falsificar paquetes más fácilmente) también está diseñado para la mensajería instantánea y no para la comunicación de la máquina. No se necesita ninguno de esos modos, solo use SRP: una vez que tenga una clave simétrica negociada mutuamente, simplemente poder cifrar algo es suficiente garantía de que está hablando con el tercero correcto. Además, nuevamente, vuelva a leer mis últimos dos párrafos.
Jonathan Dickinson
1
En realidad, tengo una sugerencia aún mejor: use un DTLS existente sobre la implementación UDP y no intente rodar el suyo. Le ahorrará tiempo, y hay muchos detalles pequeños pero críticos que es fácil equivocarse si intenta diseñar su propia capa de cifrado de datagramas.
Ilmari Karonen
2

Creo que mi último comentario a la excelente respuesta de Jonathan vale la pena expandirlo a una respuesta propia:

Si no tiene mucha experiencia en criptografía, no debe intentar diseñar su propia capa de cifrado si puede evitarla. Si lo tienen mucha experiencia de cifrado, debe saber mejor que diseñar su propia capa de cifrado si puede evitarlo.

En su lugar, intente encontrar una biblioteca criptográfica existente, estandarizada y probada que haga lo que necesita. En su caso, recomendaría GnuTLS , que, según Wikipedia , proporciona autenticación TLS-SRP ( RFC 5054 ) y comunicación UDP segura con DTLS ( RFC 6347 ). El primero se encarga de iniciar sesión, mientras que el segundo protege el canal seguro formado de ataques activos y de espionaje, e incluso puede protegerlo de los ataques de repetición .

Ilmari Karonen
fuente
Estoy usando TCP Este es un tipo de juego muy diferente para un cliente específico. Similar a los juegos de azar / apuestas, toda la información que se puede utilizar para secuestrar el proceso aumenta las posibilidades de pérdidas innecesarias por parte de la casa. Necesitamos mantener los datos extremadamente seguros, porque la información es dinero en este caso.
Robinicks
OK, si está utilizando TCP, entonces es aún más fácil: puede usar TLS 1.2 normal en lugar de DTLS, lo que le brinda más opciones para elegir. Sin embargo, todavía recomendaría la biblioteca GnuTLS.
Ilmari Karonen
Investigaré un poco y veré si puedo referirme al código fuente TLS tanto en el lado del cliente como del servidor, y basaré mi protocolo en lo que hace. ¿Sería esto lo suficientemente fuerte? Esencialmente es solo cifrado de paquetes con algún cifrado / modo, ¿correcto?
Robinicks
No, hay mucho más en el protocolo TLS que eso. Es por eso que desea utilizar una biblioteca estándar que la implemente, en lugar de crear la suya propia.
Ilmari Karonen