Authentification entre le client, le serveur central et le serveur exécuté par le joueur

8

Je développe un jeu open source qui utilise un schéma client-serveur similaire à Minecraft. Nous contrôlerons le serveur d'authentification central qui vérifie qu'un compte est valide, tandis que les joueurs exécuteront leurs propres serveurs.

L'authentification du client est simple, mais comment le serveur peut-il savoir que l'utilisateur est valide, sans avoir accès à ses informations d'identification ou à son jeton de session?

Par exemple:

  • Client> Serveur d'authentification : envoie les informations d'identification de l'utilisateur.
  • Serveur d'authentification> Client: répond avec un ID de session si la connexion est valide.

Ensuite, le client peut se connecter au serveur, mais le serveur n'a aucun moyen de vérifier si le client est bien celui qu'il dit. Ces serveurs sont gérés par des joueurs, ce qui leur permet de modifier facilement le serveur et de collecter les données utilisateur. (Seul le serveur central d'authentification peut être approuvé)

Le serveur d'authentification pourrait accepter les connexions TCP, mais je me demande si HTTPS serait plus facile dans ce cas, car obtenir une réponse est plus facile que d'établir un écouteur de chaque côté, en particulier pour seulement quelques demandes.

Cyral
la source

Réponses:

3

Edit: Après avoir posté cela, j'ai réalisé que c'était presque exactement la même réponse donnée par Ali.S (légèrement différente mais l'approche globale est la même.) Cela a commencé comme quelque chose de complètement différent.

Cette méthode suppose que toutes les communications sont maintenues sur une série de tunnels sécurisés. Peu importe comment vous y parvenez. Je proposerais TLS, mais c'est juste moi.

  1. Client => Game Server Le client se connecte au serveur de jeu et lance une session de connexion.
  2. Game Server => Auth Server Le serveur de jeu se connecte au serveur d'authentification et demande un jeton d'ID de session au serveur d'authentification. Cette connexion est maintenue ouverte pour écouter la réussite / l'échec de la connexion.
  3. Game Server => Client Le jeton d'ID de session est renvoyé au client.
  4. Client => Serveur Auth Le client envoie l'ID de session au serveur Auth avec le nom d'utilisateur et le mot de passe de l'utilisateur, et quelques informations sur le serveur (IP, clé publique TLS, etc. Voir les notes de bas de page)
  5. Serveur d' authentification => Serveur de jeu Le serveur d'authentification envoie ensuite des informations sur la connexion au serveur de jeu (état de réussite, nom d'utilisateur, statistiques, etc.) à l'aide de l'ID de session fourni par le client.
  6. Serveur de jeu => Client Le serveur de jeu informe le client que l'authentification a réussi et lui permet d'entrer.
  7. Toutes les connexions, à l'exception de la connexion initiale du client au serveur de jeu, sont désormais interrompues.

Alternativement, vous pouvez donner aux serveurs de jeu un port dédié pour écouter les connexions. Si vous choisissez cette route, le flux devrait ressembler à ceci:

  1. Client => Auth Server Le client envoie le nom d'utilisateur, le mot de passe et l'adresse IP du serveur au serveur d'authentification.
  2. Serveur d'authentification => Serveur de jeu + client Si la connexion réussit, le serveur d'authentification envoie un jeton unique au serveur de jeu et au client. Envoyez également l'IP du client au serveur de jeu, afin que le jeton ne puisse pas être volé.
  3. Client => Game Server Le client envoie ensuite le jeton au serveur de jeu, où il est ensuite vérifié et supprimé sur le serveur de jeu. Le serveur de jeu laisse ensuite entrer le client.

Cette deuxième approche faciliterait un peu la mise en œuvre globale.

Notes de bas de page:

La raison pour laquelle je spécifie que certaines informations doivent être envoyées sur le serveur de jeu au serveur d'authentification est de renforcer le processus contre les usurpations. Le serveur peut vérifier les informations pour s'assurer qu'il autorise la connexion attendue par le lecteur.

Les identifiants de session n'auraient pas à être cryptographiquement sécurisés, bien que cela rendrait les connexions d'usurpation un peu plus difficiles s'ils l'étaient.

Si vous choisissez de suivre la route TLS, vous pouvez configurer un serveur de signature qui signe tous les certificats utilisés par votre infrastructure et l'ajouter en tant qu'autorité de certification de confiance dans le logiciel client / serveur. Tant que vous ne laissez pas votre certificat de signature se desserrer, vous pourrez fournir une authentification décente.

Pour atténuer les attaques DoS, effectuez le délai d'expiration des connexions après 20 secondes ou moins. Si cela dure plus longtemps que cela, alors quelque chose ne va pas et vous n'avez pas besoin d'attendre 3 minutes pour que la connexion expire d'elle-même.

Kaslai
la source
Notez que votre flux alternatif ne fonctionnera probablement pas pour les clients qui se trouvent derrière des périphériques NAT "parallèles" (classés comme "stricts" par le programme Xbox Live de Microsoft). Et peut également avoir des problèmes si deux clients se trouvent simultanément derrière le même périphérique NAT (selon les spécificités de la façon dont leur périphérique NAT gère cette situation); c'est parce que le serveur de jeu peut voir une adresse IP + un port différent de celui du serveur d'authentification, simplement en raison de NAT. La première approche répertoriée devrait fonctionner sans problème dans tous les cas.
Trevor Powell
Juste pour clarifier la terminologie, le client (le joueur) n'aurait aucune exigence particulière à lui imposer pour le deuxième flux. Seul le serveur de jeu aurait besoin d'un mappage de port dédié pour cette méthode. Comme il sert déjà le jeu sur un port dédié, cela ne devrait pas être trop demander. L'ensemble du processus est démarré par le client initialisant une connexion avec le serveur d'authentification, ce que tout appareil sur Internet peut faire, quelle que soit la sévérité de leur NAT.
Kaslai
En relisant votre commentaire, je pense que je vois quel était votre problème. Dans le cas d'un utilisateur utilisant une sorte d'équilibreur de charge qui peut théoriquement envoyer la demande d'authentification via une IP et la demande de connexion au jeu via une autre IP, cela peut être résolu en utilisant la solution d'Ali S.
Kaslai
Oui, c'est ce que j'avais l'intention de souligner (mais peut-être que ce n'est pas clair). Sous NAT "strict" (selon la définition de Microsoft), le serveur d'authentification et le serveur de jeu ne verront pas la même IP: valeurs de port pour un seul joueur, de sorte que le serveur d'authentification ne peut pas utilement indiquer au serveur de jeu l'adresse IP / le port à attendre à voir. Ce problème peut également se produire avec un NAT "modéré" (selon l'implémentation de NAT spécifique) s'il y a deux joueurs derrière le même périphérique NAT, essayant tous les deux d'envoyer à partir du même numéro de port.
Trevor Powell
Ah, eh bien je pensais juste que l'IP lui-même devait être pris en compte. Le port n'a pas vraiment d'importance; C'est juste pour empêcher un tiers malveillant de voler le jeton et de l'utiliser ailleurs. Peu importe qu'il y ait plusieurs utilisateurs derrière le même NAT, car le jeton identifiera l'utilisateur réel, il n'y a donc pas de problème de collision à craindre.
Kaslai
2

Le client doit avoir une clé privée et une clé publique .

La clé privée doit être l'identifiant unique que le client reçoit du serveur d'authentification. La clé publique doit également être envoyée au client.

Avant que le client ne se connecte à un serveur de jeux, il doit envoyer un message avec sa clé privée et l'adresse IP du serveur de jeux auquel il veut se connecter, au serveur d'authentification. Le serveur d'authentification doit ensuite vérifier et rechercher la correspondance pour la clé privée et stocker la clé publique dans ses enregistrements.

Le serveur de jeu auquel le client se connecte doit envoyer une demande au serveur d'authentification après avoir obtenu la clé publique du client. Si le serveur d'authentification peut vérifier que le client souhaite se connecter à cette adresse IP du serveur de jeu, renvoyez qu'il s'agit d'un client correct. Le serveur de jeu doit alors permettre au client de se connecter.

La clé privée n'est utilisée que pour l'authentification du client afin que le serveur de jeu n'obtienne pas le véritable identifiant d'authentification.

Statique
la source
1
Je pense que je comprends le processus utilisé. J'ai écrit une sorte de diagramme: i.pyratron.com/MXkZXU.png Ces informations semblent-elles correctes?
Cyral
@Cyral Cela semble correct.
Statique
1

Il y a plusieurs solutions auxquelles je peux penser, mais voici la plus sûre:

  1. le client se connecte au serveur.
  2. le client demande un pont d'authentification.
  3. le serveur se connecte au serveur d'authentification, agissant comme un proxy entre le lecteur et l'authentification. serveur.
  4. client et serveur d'authentification, forment une session SSL sur ce pont nouvellement formé.
  5. en utilisant cette connexion sécurisée sur le pont, le client se connecte au serveur d'authentification.
  6. le serveur d'authentification indique au serveur de jeu si la connexion a réussi ou non, via une autre connexion TCP. puis déconnecte sa connexion pont / connexion.
  7. le client et le serveur de jeux peuvent désormais reprendre la communication (uniquement) sur une connexion déjà existante (qui a été utilisée pour l'authentification).

Notez que, dans ce scénario, le serveur de jeu n'a en fait aucun moyen d'écouter, même si toute l'authentification le traverse. pour la même raison, votre FAI ne peut pas surveiller les paquets que vous envoyez à Facebook ou qui proviennent de Facebook.

Ali1S232
la source
Techniquement, le FAI a accès aux données brutes.
Statique
@HaroldSeefeld Techniquement pas ceux qui passent par la connexion IPSec / HTTPS.
Ali1S232
1

Pour ce faire, je demanderais au serveur Auth d'envoyer un jeton au client après la connexion avec la liste des serveurs de jeux validés (afin que le client puisse être sûr que le serveur de jeux est valide).

Ensuite, le client enverrait le jeton au serveur de jeu, qui l'enverrait ensuite au serveur Auth pour confirmer qu'il s'agit du client valide.

S'identifier:

  1. Client vers serveur Auth: nom d'utilisateur et mot de passe crypté
  2. Auth server to Client: token

Plus tard lors de l'adhésion à un serveur de jeu:

  1. Client vers serveur de jeu: le jeton mentionné précédemment
  2. Serveur de jeu vers serveur Auth: encore une fois le jeton
  3. Du serveur d'authentification au serveur de jeu: si le jeton est valide, le signal OK
  4. Serveur de jeu au client: permet au client de se joindre
zoran404
la source
0

Que diriez-vous de signer un jeton JWT avec un secret que seul le serveur central d'authentification et de lecture connaît? Il vous permet de signer json, ce qui peut être vérifié plus tard.

Ben Aubin
la source
Cela ne permettrait-il pas aux serveurs gérés par les joueurs de voler les informations d'identification de leurs utilisateurs?
idbrii
Non, 2 façons de le faire: 1 - le client demande un jwt avec le serveur, allwoying le serveur pour voler l'identité, mais seulement sur leur serveur (pas un gros problème) 2 - JWT ne fonctionne qu'une seule fois
Ben Aubin