Autenticación entre el cliente, el servidor central y el servidor ejecutado por el jugador


8

Estoy desarrollando un juego de código abierto que utiliza un esquema cliente-servidor similar a Minecraft. Controlaremos el servidor de autenticación central que verifica que una cuenta sea válida, mientras que los jugadores ejecutarán sus propios servidores.

Autenticar al cliente es simple, pero ¿cómo puede saber el servidor que el usuario es válido, sin tener acceso a sus credenciales o token de sesión?

Por ejemplo:

  • Cliente> Servidor de autenticación: envía credenciales de usuario.
  • Servidor de autenticación> Cliente: responde con un ID de sesión si es un inicio de sesión válido.

Luego, el cliente puede conectarse al servidor, pero el servidor no tiene forma de verificar si el cliente es quien dice. Los jugadores ejecutan estos servidores, lo que les facilita modificar el servidor y recopilar los datos del usuario. (Solo se puede confiar en el servidor de autenticación central)

El servidor de autenticación podría aceptar conexiones TCP, pero me pregunto si HTTPS sería más fácil en este caso, ya que obtener una respuesta es más fácil que establecer un escucha en cada lado, especialmente para unas pocas solicitudes.

Respuestas:


3

Editar: Después de publicar esto, me di cuenta de que es casi la misma respuesta dada por Ali.S (ligeramente diferente, pero el enfoque general es el mismo). Sin embargo, comenzó como algo completamente diferente.

Este método supone que todas las comunicaciones se mantienen en una serie de túneles seguros. Cómo lograr esto no importa. Sugeriría TLS, pero solo soy yo.

  1. Cliente => Servidor del juego El cliente se conecta al servidor del juego e inicia una sesión de inicio de sesión.
  2. Servidor de juegos => Servidor de autenticación El servidor de juegos se conecta al servidor de autenticación y solicita un token de ID de sesión del servidor de autenticación. Esta conexión se mantiene abierta para escuchar el inicio / error de inicio de sesión.
  3. Game Server => Cliente El token de ID de sesión se envía de vuelta al cliente.
  4. Cliente => Servidor de autenticación El cliente envía la ID de sesión al servidor de autenticación junto con el nombre de usuario y la contraseña del usuario, y cierta información sobre el servidor (IP, clave pública TLS, etc. Ver notas al pie)
  5. Servidor de autenticación => Servidor de juegos El servidor de autenticación envía información sobre el inicio de sesión al servidor de juegos (estado de éxito, nombre de usuario, estadísticas, etc.) utilizando el ID de sesión proporcionado por el cliente.
  6. Servidor de juegos => Cliente El servidor de juegos le dice al cliente que la autenticación fue exitosa y los deja entrar.
  7. Todas las conexiones, excepto la conexión inicial del cliente al servidor del juego, ahora se eliminan.

Alternativamente, puede dar a los servidores del juego un puerto dedicado para escuchar los inicios de sesión. Si elige esta ruta, el flujo se vería así:

  1. Cliente => Servidor de autenticación El cliente envía el nombre de usuario, la contraseña y la IP del servidor al servidor de autenticación.
  2. Auth Server => Game Server + Client Si el inicio de sesión es exitoso, el servidor de autenticación envía un token único al servidor y al cliente del juego. Envíe también la IP del cliente al servidor del juego, para que no se pueda robar el token.
  3. Cliente => Servidor del juego El cliente envía el token al servidor del juego, donde luego se verifica y elimina en el servidor del juego. El servidor del juego luego deja entrar al cliente.

Este segundo enfoque facilitaría un poco la implementación general.

Notas al pie:

La razón por la que especifico que se debe enviar cierta información sobre el servidor del juego al servidor de autenticación es para endurecer el proceso contra las falsificaciones. El servidor puede verificar la información para asegurarse de que está autorizando la conexión que el jugador espera.

Las ID de sesión no tendrían que ser criptográficamente seguras, aunque haría que las conexiones de suplantación fueran algo más difíciles si lo fueran.

Si elige ir a la ruta TLS, puede configurar un servidor de firma que firme todos los certificados utilizados por su infraestructura y agregarlo como una CA confiable en el software cliente / servidor. Mientras no permita que su certificado de firma se pierda, podrá proporcionar una autenticación decente.

En aras de mitigar los ataques DoS, agota el tiempo de espera de las conexiones después de 20 segundos o menos. Si dura más que eso, entonces algo está mal y no necesita esperar 3 minutos esperando que la conexión se agote por sí sola.


Tenga en cuenta que es probable que su flujo alternativo no funcione para clientes que están detrás de dispositivos NAT "paralelos" (clasificados como "estrictos" por el programa Xbox Live de Microsoft). Y de manera similar puede tener problemas si dos clientes están simultáneamente detrás del mismo dispositivo NAT (dependiendo de los detalles de cómo su dispositivo NAT maneja esa situación); Esto se debe a que el servidor del juego puede ver una dirección IP + puerto diferente que el servidor de autenticación, solo debido a NAT. El primer enfoque enumerado debería funcionar sin problemas en todos los casos.
Trevor Powell

Solo para aclarar la terminología, el Cliente (el jugador) no tendría requisitos especiales para el segundo flujo. Solo el servidor del juego necesitaría una asignación de puertos dedicada para este método. Como ya está sirviendo el juego en un puerto dedicado, esto no debería ser mucho pedir. El cliente inicia todo el proceso inicializando una conexión con el servidor de autenticación, lo que puede hacer cualquier dispositivo en Internet, independientemente de cuán estricto sea su NAT.
Kaslai

Al volver a leer su comentario, creo que veo cuál fue su problema. En el caso de un usuario que utiliza algún tipo de equilibrador de carga que teóricamente puede enviar la solicitud de autenticación a través de una IP y la solicitud de conexión del juego a través de otra IP, eso se puede resolver con la solución de Ali S.
Kaslai

Sí, eso es lo que tenía la intención de señalar (pero tal vez no lo dejé claro). Bajo NAT "estricto" (según la definición de Microsoft), el servidor de autenticación y el servidor del juego no verán la misma IP: valores de puerto para un solo jugador, por lo que el servidor de autenticación no puede decirle al servidor del juego la IP / puerto que debe esperar. para ver. Este problema también puede ocurrir con NAT "moderado" (dependiendo de la implementación de NAT específica) si hay dos jugadores detrás del dispositivo NAT, ambos intentando enviar desde el mismo número de puerto.
Trevor Powell

Ah, bueno, solo estaba pensando que la IP en sí debería ser considerada. El puerto realmente no importa; Es solo para evitar que un tercero malintencionado robe el token y lo use en otro lugar. Realmente no importa si hay varios usuarios detrás del mismo NAT, ya que el token identificará al usuario real, por lo que no hay problemas de colisión de los que preocuparse.
Kaslai

2

El cliente debe tener una clave privada y una pública .

La clave privada debe ser el identificador único que el cliente recibe del servidor de autenticación. La clave pública también debe enviarse al cliente.

Antes de que el cliente se conecte a un servidor de juegos, debe enviar un mensaje con su clave privada y la ip del servidor de juegos al que desea conectarse, al servidor de autenticación. El servidor de autenticación debería verificar y encontrar la coincidencia para la clave privada y almacenar la clave pública en sus registros.

El servidor de juegos al que se conecta el cliente debe enviar una solicitud al servidor de autenticación después de obtener la clave pública del cliente. Si el servidor de autenticación puede verificar que el cliente desea conectarse a esa IP del servidor del juego, envíe que es un cliente correcto. El servidor del juego debería permitir que el cliente se conecte.

La clave privada solo se usa para la autenticación del cliente para que el servidor del juego no obtenga la identificación de autenticación real.


1
Creo que entiendo el proceso utilizado. Escribí un tipo de diagrama de flujo: i.pyratron.com/MXkZXU.png ¿Esta información parece correcta?
Cyral

@Cyral Eso parece correcto.
Estática

1

Hay varias soluciones en las que puedo pensar, pero esta es la más segura:

  1. El cliente se conecta al servidor.
  2. El cliente solicita un puente de autenticación.
  3. El servidor se conecta al servidor de autenticación, actuando como un proxy entre el jugador y la autenticación. servidor.
  4. cliente y servidor de autenticación, forman una sesión SSL sobre este puente recién formado.
  5. Al utilizar esta conexión segura a través del puente, el cliente inicia sesión en el servidor de autenticación.
  6. auth server le dice al servidor del juego si el inicio de sesión fue exitoso o no, a través de alguna otra conexión TCP. luego desconecta su conexión de puente / inicio de sesión.
  7. El cliente y el servidor del juego ahora pueden reanudar la comunicación (solo) a través de una conexión ya existente (que se utilizó para la autenticación).

Tenga en cuenta que, en este escenario, el servidor de juego en realidad no tiene forma de espiar, a pesar de que toda la autenticación está pasando por él. por la misma razón, su ISP no puede monitorear qué paquetes envía a Facebook o si provienen de Facebook.


Técnicamente, el ISP tiene acceso a los datos sin procesar.
Estático

@HaroldSeefeld Técnicamente no son los que pasan por la conexión IPSec / HTTPS.
Ali1S232

1

La forma en que haría esto es haciendo que el servidor Auth envíe un token al Cliente después de iniciar sesión junto con una lista de servidores de Juego validados (para que el Cliente pueda estar seguro de que el servidor del Juego es válido).

Luego, el Cliente enviaría el token al servidor del Juego, que luego lo enviaría al servidor Auth para confirmar que este es el cliente válido.

Iniciar sesión:

  1. Cliente a servidor de autenticación: nombre de usuario y contraseña cifrada
  2. Servidor de autenticación al cliente: token

Más tarde, cuando te unas a un servidor de juegos:

  1. Cliente a servidor del juego: el token mencionado anteriormente
  2. Servidor de juego a servidor de autenticación: nuevamente el token
  3. Auth server to Game server: si el token es válido, entonces señal OK
  4. Servidor del juego al cliente: permite que el cliente se una

0

¿Qué tal firmar un token JWT con un secreto que solo el servidor central de autenticación y el jugador conoce? Le permite firmar json, que se puede verificar más adelante.


¿No permitiría eso que los servidores ejecutados por jugadores roben las credenciales de sus usuarios?
idbrii

No, hay 2 formas de hacer esto: 1 - el cliente solicita un jwt con el servidor en él, todo lo que el servidor roba identidad, pero solo en su servidor (no es gran cosa) 2 - JWT solo funciona una vez
Ben Aubin
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.