Authentifizierung zwischen Client, zentralem Server und vom Player ausgeführtem Server

8

Ich entwickle ein Open-Source-Spiel, das ein Client-Server-Schema verwendet, das Minecraft ähnelt. Wir werden den zentralen Authentifizierungsserver steuern, der überprüft, ob ein Konto gültig ist, während die Spieler ihre eigenen Server betreiben.

Die Authentifizierung des Clients ist einfach. Wie kann der Server jedoch feststellen, dass der Benutzer gültig ist, ohne Zugriff auf Anmeldeinformationen oder Sitzungstoken zu haben?

Zum Beispiel:

  • Client> Auth Server: Sendet Benutzeranmeldeinformationen.
  • Auth Server> Client: Antwortet mit einer Sitzungs-ID, wenn die Anmeldung gültig ist.

Dann kann der Client eine Verbindung zum Server herstellen, aber der Server kann nicht überprüfen, ob der Client derjenige ist, der er sagt. Diese Server werden von Spielern betrieben, wodurch sie den Server leicht ändern und die Benutzerdaten sammeln können. (Nur dem zentralen Authentifizierungsserver kann vertraut werden.)

Der Authentifizierungsserver könnte TCP-Verbindungen akzeptieren, aber ich frage mich, ob HTTPS in diesem Fall einfacher wäre, da das Abrufen einer Antwort einfacher ist als das Einrichten eines Listeners auf jeder Seite, insbesondere für nur wenige Anforderungen.

Cyral
quelle

Antworten:

3

Bearbeiten: Nachdem ich dies gepostet hatte, wurde mir klar, dass es fast genau die gleiche Antwort von Ali.S ist (etwas anders, aber der Gesamtansatz ist der gleiche.) Es begann jedoch als etwas völlig anderes.

Bei dieser Methode wird davon ausgegangen, dass die gesamte Kommunikation über eine Reihe sicherer Tunnel erfolgt. Wie Sie dies erreichen, spielt keine Rolle. Ich würde TLS vorschlagen, aber das bin nur ich.

  1. Client => Spieleserver Der Client stellt eine Verbindung zum Spieleserver her und initiiert eine Anmeldesitzung.
  2. Spieleserver => Authentifizierungsserver Der Spieleserver stellt eine Verbindung zum Authentifizierungsserver her und fordert vom Authentifizierungsserver ein Sitzungs-ID-Token an. Diese Verbindung wird offen gehalten, um auf den Erfolg / Misserfolg der Anmeldung zu warten.
  3. Game Server => Client Das Sitzungs-ID-Token wird an den Client zurückgesendet.
  4. Client => Authentifizierungsserver Der Client sendet die Sitzungs-ID zusammen mit dem Benutzernamen und dem Kennwort des Benutzers sowie einigen Informationen zum Server (IP, öffentlicher TLS-Schlüssel usw. siehe Fußnoten) an den Authentifizierungsserver.
  5. Auth Server => Game Server Der Auth Server sendet dann Informationen über die Anmeldung an den Game Server (Erfolgsstatus, Benutzername, Statistiken usw.) unter Verwendung der vom Client bereitgestellten Sitzungs-ID.
  6. Spieleserver => Client Der Spielserver teilt dem Client mit, dass die Authentifizierung erfolgreich war, und lässt sie ein.
  7. Alle Verbindungen mit Ausnahme der ursprünglichen Verbindung zwischen Client und Spielserver werden jetzt abgebrochen.

Alternativ können Sie den Spielservern einen dedizierten Port zum Abhören von Anmeldungen zuweisen. Wenn Sie diese Route wählen, sieht der Ablauf folgendermaßen aus:

  1. Client => Authentifizierungsserver Der Client sendet den Benutzernamen, das Kennwort und die Server-IP an den Authentifizierungsserver.
  2. Auth Server => Game Server + Client Wenn die Anmeldung erfolgreich ist, sendet der Auth Server ein eindeutiges Token an den Game Server und den Client. Senden Sie die IP des Clients auch an den Spieleserver, damit das Token nicht gestohlen werden kann.
  3. Client => Spieleserver Der Client sendet das Token dann an den Spieleserver, wo es überprüft und auf dem Spieleserver gelöscht wird. Der Spieleserver lässt dann den Client ein.

Dieser zweite Ansatz würde die Gesamtimplementierung etwas erleichtern.

Fußnoten:

Der Grund, warum ich spezifiziere, dass einige Informationen über den Spieleserver an den Authentifizierungsserver gesendet werden sollen, besteht darin, den Prozess gegen Parodien abzusichern. Der Server kann die Informationen überprüfen, um sicherzustellen, dass er die vom Player erwartete Verbindung autorisiert.

Sitzungs-IDs müssten nicht kryptografisch sicher sein, obwohl dies das Spoofing von Verbindungen etwas erschweren würde.

Wenn Sie sich für die TLS-Route entscheiden, können Sie einen Signaturserver einrichten, der alle von Ihrer Infrastruktur verwendeten Zertifikate signiert, und ihn als vertrauenswürdige Zertifizierungsstelle in der Client / Server-Software hinzufügen. Solange Sie nicht zulassen, dass sich Ihr Signaturzertifikat löst, können Sie eine anständige Authentifizierung bereitstellen.

Um DoS-Angriffe abzuschwächen, stellen Sie nach 20 oder weniger Sekunden eine Zeitüberschreitung für Verbindungen her. Wenn es länger dauert, stimmt etwas nicht und Sie müssen nicht 3 Minuten warten, bis die Verbindung von selbst eine Zeitüberschreitung aufweist.

Kaslai
quelle
Beachten Sie, dass Ihr alternativer Datenfluss wahrscheinlich nicht für Clients funktioniert, die sich hinter "parallelen" NAT-Geräten befinden (vom Microsoft Xbox Live-Programm als "streng" eingestuft). Und kann ebenfalls Probleme haben, wenn sich zwei Clients gleichzeitig hinter demselben NAT-Gerät befinden (abhängig von den Besonderheiten, wie ihr NAT-Gerät mit dieser Situation umgeht). Dies liegt daran, dass der Spieleserver möglicherweise aufgrund von NAT eine andere IP-Adresse + einen anderen Port als der Authentifizierungsserver sieht. Der erste aufgeführte Ansatz sollte in allen Fällen problemlos funktionieren.
Trevor Powell
Um die Terminologie klar zu machen, hätte der Kunde (der Spieler) keine besonderen Anforderungen an ihn für den zweiten Ablauf. Nur der Spieleserver würde für diese Methode eine dedizierte Portzuordnung benötigen. Da das Spiel bereits über einen dedizierten Port bereitgestellt wird, sollte dies nicht zu viel verlangt werden. Der gesamte Prozess wird gestartet, indem der Client eine Verbindung mit dem Authentifizierungsserver initialisiert, die jedes Gerät im Internet ausführen kann, unabhängig davon, wie streng sein NAT ist.
Kaslai
Wenn ich Ihren Kommentar noch einmal lese, sehe ich, was Ihr Problem war. Wenn ein Benutzer eine Art Load Balancer verwendet, der theoretisch die Authentifizierungsanforderung über eine IP und die Spielverbindungsanforderung über eine andere IP senden kann, kann dies mit der Lösung von Ali S gelöst werden.
Kaslai
Ja, darauf wollte ich hinweisen (machte es aber vielleicht nicht klar). Unter "striktem" NAT (gemäß der Definition von Microsoft) sehen der Authentifizierungsserver und der Spieleserver nicht die gleichen IP: Port-Werte für einen einzelnen Spieler, sodass der Authentifizierungsserver dem Spieleserver nicht sinnvoll mitteilen kann, welche IP / welcher Port zu erwarten ist sehen. Dieses Problem kann auch bei "moderatem" NAT auftreten (abhängig von der spezifischen NAT-Implementierung), wenn sich hinter einem NAT-Gerät zwei Player befinden, die beide versuchen, von derselben Portnummer aus zu senden.
Trevor Powell
Ah, nun, ich dachte nur, dass die IP selbst berücksichtigt werden sollte. Der Hafen spielt keine Rolle; Es soll nur verhindern, dass ein böswilliger Dritter das Token stiehlt und es anderweitig verwendet. Es spielt keine Rolle, ob sich mehrere Benutzer hinter demselben NAT befinden, da das Token den tatsächlichen Benutzer identifiziert, sodass keine Kollisionsprobleme zu befürchten sind.
Kaslai
2

Der Client sollte einen privaten und einen öffentlichen Schlüssel haben.

Der private Schlüssel sollte die eindeutige Kennung sein, die der Client vom Authentifizierungsserver erhält. Der öffentliche Schlüssel sollte auch an den Client gesendet werden.

Bevor der Client eine Verbindung zu einem Spieleserver herstellt, sollte er eine Nachricht mit seinem privaten Schlüssel und der IP-Adresse des Spieleservers, zu dem er eine Verbindung herstellen möchte, an den Authentifizierungsserver senden. Der Authentifizierungsserver sollte dann die Übereinstimmung für den privaten Schlüssel überprüfen und finden und den öffentlichen Schlüssel in seinen Datensätzen speichern.

Der Spieleserver, zu dem der Client eine Verbindung herstellt, sollte nach Erhalt des öffentlichen Schlüssels des Clients eine Anforderung an den Authentifizierungsserver senden. Wenn der Authentifizierungsserver überprüfen kann, ob der Client eine Verbindung zu dieser IP des Spielservers herstellen möchte, senden Sie, dass der Client in Ordnung ist. Der Spieleserver sollte dann dem Client erlauben, eine Verbindung herzustellen.

Der private Schlüssel wird nur zur Authentifizierung des Clients verwendet, damit der Spieleserver nicht die echte Authentifizierungs-ID erhält.

Statisch
quelle
1
Ich glaube, ich verstehe den verwendeten Prozess. Ich habe so etwas wie ein Flussdiagramm geschrieben: i.pyratron.com/MXkZXU.png Scheint diese Information korrekt zu sein?
Cyral
@ Cyral Das sieht richtig aus.
Statisch
1

Es gibt mehrere Lösungen, an die ich denken kann, aber hier ist die sicherste:

  1. Client mit Server verbinden.
  2. Der Client fordert eine Authentifizierungsbrücke an.
  3. Der Server stellt eine Verbindung zum Authentifizierungsserver her und fungiert als Proxy zwischen Player und Authentifizierung. Server.
  4. Client und Authentifizierungsserver bilden eine SSL-Sitzung über diese neu gebildete Brücke.
  5. Über diese sichere Verbindung über die Brücke meldet sich der Client beim Authentifizierungsserver an.
  6. Der Authentifizierungsserver teilt dem Spieleserver über eine andere TCP-Verbindung mit, ob die Anmeldung erfolgreich war oder nicht. Trennt dann die Bridge / Login-Verbindung.
  7. Client und Spieleserver können jetzt die Kommunikation (nur) über eine bereits vorhandene Verbindung (die zur Authentifizierung verwendet wurde) wieder aufnehmen.

Beachten Sie, dass der Spieleserver in diesem Szenario tatsächlich keine Möglichkeit zum Abhören hat, obwohl die gesamte Authentifizierung durchlaufen wird. Aus dem gleichen Grund kann Ihr ISP nicht überwachen, welche Pakete Sie an Facebook senden oder von Facebook kommen.

Ali1S232
quelle
Technisch hat der ISP Zugriff auf die Rohdaten.
Statisch
@HaroldSeefeld Technisch nicht diejenigen, die über eine IPSec / HTTPS-Verbindung gehen.
Ali1S232
1

Ich würde dies tun, indem ich den Auth-Server nach der Anmeldung ein Token an den Client senden lasse, zusammen mit einer Liste der validierten Spieleserver (damit der Client sicher sein kann, dass der Spieleserver gültig ist).

Dann würde der Client das Token an den Spieleserver senden, der es dann an den Auth-Server senden würde, um zu bestätigen, dass dies der gültige Client ist.

Anmeldung:

  1. Client zu Auth-Server: Benutzername und verschlüsseltes Passwort
  2. Authentifizierungsserver an Client: Token

Später beim Beitritt zu einem Spieleserver:

  1. Client-to-Game-Server: Das zuvor erwähnte Token
  2. Spieleserver zu Auth-Server: wieder das Token
  3. Authentifizierungsserver an Spieleserver: Wenn das Token gültig ist, wird das OK-Signal angezeigt
  4. Spieleserver zum Client: Ermöglicht dem Client den Beitritt
zoran404
quelle
0

Wie wäre es, wenn Sie ein JWT- Token mit einem Geheimnis signieren, das nur der zentrale Authentifizierungs- und Player-Server kennt? Damit können Sie json signieren, was später überprüft werden kann.

Ben Aubin
quelle
Würde das nicht den von Spielern betriebenen Servern erlauben, die Anmeldeinformationen ihrer Benutzer zu stehlen?
idbrii
Nein, zwei Möglichkeiten, dies zu tun: 1 - Der Client bittet um ein JWT mit dem Server darin, wodurch der Server die Identität stehlen kann, aber nur auf seinem Server (keine große Sache). 2 - JWT funktioniert nur einmal
Ben Aubin