Autenticazione tra client, server centrale e player con server eseguito


8

Sto sviluppando un gioco open source che utilizza uno schema client-server simile a Minecraft. Controlleremo il server di autenticazione centrale che verifica che un account sia valido, mentre i giocatori eseguiranno i propri server.

L'autenticazione del client è semplice, ma come fa il server a sapere che l'utente è valido, senza avere accesso a credenziali o token di sessione?

Per esempio:

  • Client> Server di autenticazione: invia le credenziali dell'utente.
  • Server di autenticazione> Client: risponde con un ID di sessione se l'accesso è valido.

Quindi, il client può connettersi al server, ma il server non ha modo di verificare se il client è chi dice. Questi server sono gestiti dai giocatori, il che semplifica la modifica del server e la raccolta dei dati dell'utente. (Solo il server di autenticazione centrale può essere considerato attendibile)

Il server di autenticazione potrebbe accettare connessioni TCP, ma mi chiedo se HTTPS sarebbe più semplice in questo caso, poiché ottenere una risposta è più semplice che stabilire un listener su ciascun lato, specialmente solo per alcune richieste.

Risposte:


3

Modifica: dopo aver pubblicato questo mi sono reso conto che è quasi la stessa identica risposta data da Ali.S (leggermente diverso ma l'approccio generale è lo stesso.) È iniziato come qualcosa di completamente diverso.

Questo metodo presuppone che tutte le comunicazioni siano mantenute su una serie di tunnel sicuri. Non importa come raggiungi questo obiettivo. Suggerirei TLS, ma sono solo io.

  1. Client => Server di gioco Il client si connette al server di gioco e avvia una sessione di accesso.
  2. Server di gioco => Server di autenticazione Il server di gioco si collega al server di autenticazione e richiede un token ID di sessione dal server di autenticazione. Questa connessione è mantenuta aperta per ascoltare l'esito positivo / negativo dell'accesso.
  3. Game Server => Client Il token ID sessione viene inviato al client.
  4. Client => Server di autenticazione Il client invia l'ID di sessione al server di autenticazione insieme al nome utente e alla password dell'utente e ad alcune informazioni sul server (IP, chiave pubblica TLS, ecc. Vedi le note a piè di pagina)
  5. Server di autenticazione => Server di gioco Il server di autenticazione invia quindi informazioni sull'accesso al server di gioco (stato di successo, nome utente, statistiche, ecc.) Utilizzando l'ID sessione fornito dal client.
  6. Game Server => Client Il server di gioco comunica al client che l'autent ha avuto successo e li fa entrare.
  7. Tutte le connessioni ad eccezione della connessione iniziale tra client e server di gioco sono state demolite.

In alternativa, puoi assegnare ai server di gioco una porta dedicata per ascoltare gli accessi. Se scegli questa rotta, il flusso sarebbe simile al seguente:

  1. Client => Server di autenticazione Il client invia il nome utente, la password e l'IP del server al server di autenticazione.
  2. Server di autenticazione => Server di gioco + client Se l'accesso ha esito positivo, il server di autenticazione invia un token univoco al server di gioco e al client. Invia anche l'IP del client al server di gioco, in modo che il token non possa essere rubato.
  3. Client => Server di gioco Il client invia quindi il token al server di gioco, dove viene quindi verificato ed eliminato sul server di gioco. Il server di gioco consente quindi al client di entrare.

Questo secondo approccio renderebbe un po 'più semplice l'implementazione complessiva.

Note:

Il motivo per cui specifico che alcune informazioni dovrebbero essere inviate sul server di gioco al server di autenticazione è di rafforzare il processo contro gli spoofing. Il server può verificare le informazioni per assicurarsi che stia autorizzando la connessione prevista dal lettore.

Gli ID di sessione non dovrebbero essere crittograficamente sicuri, anche se renderebbero le connessioni di spoofing un po 'più difficili se lo fossero.

Se si sceglie di seguire il percorso TLS, è possibile configurare un server di firma che firma tutte le certificazioni utilizzate dalla propria infrastruttura e aggiungerlo come CA attendibile nel software client / server. Finché non lasci che il certificato di firma si allenti, sarai in grado di fornire un'autenticazione decente.

Per mitigare gli attacchi DoS, effettuare il timeout delle connessioni dopo 20 o meno secondi. Se dura più a lungo, qualcosa non va e non è necessario attendere 3 minuti in attesa del timeout della connessione da solo.


Si noti che è probabile che il flusso alternativo non funzioni per i client che si trovano dietro dispositivi NAT "paralleli" (classificati come "rigorosi", dal programma Microsoft Xbox Live). E allo stesso modo potrebbe avere problemi se due client sono entrambi contemporaneamente dietro lo stesso dispositivo NAT (a seconda delle specifiche di come il loro dispositivo NAT gestisce quella situazione); questo perché il server di gioco potrebbe vedere un indirizzo IP + porta diversi rispetto al server di autenticazione, solo a causa di NAT. Il primo approccio elencato dovrebbe funzionare senza problemi in tutti i casi.
Trevor Powell,

Giusto per chiarire la terminologia, il Cliente (il giocatore) non avrebbe requisiti speciali per il secondo flusso. Solo il server di gioco avrebbe bisogno di un mapping delle porte dedicato per questo metodo. Dal momento che sta già servendo il gioco su una porta dedicata, questo non dovrebbe essere troppo da chiedere. L'intero processo viene avviato dal client inizializzando una connessione con il server di autenticazione, cosa che può fare qualsiasi dispositivo su Internet, indipendentemente dalla rigidità del proprio NAT.
Kaslai,

Rileggendo il tuo commento, penso di vedere quale fosse il tuo problema. Nel caso in cui un utente utilizzi una sorta di bilanciamento del carico che può teoricamente inviare la richiesta di autenticazione tramite un IP e la richiesta di connessione del gioco tramite un altro IP, ciò può essere risolto utilizzando la soluzione di Ali S.
Kaslai,

Sì, è quello che intendevo sottolineare (ma forse non ho chiarito). In NAT "rigoroso" (secondo la definizione di Microsoft), il server di autenticazione e il server di gioco non vedranno lo stesso IP: valori di porta per un singolo giocatore, quindi il server di autenticazione non può dire utilmente al server di gioco che l'IP / porta deve aspettarsi vedere. Questo problema può verificarsi anche con NAT "moderato" (a seconda dell'implementazione NAT specifica) se ci sono due giocatori dietro un unico dispositivo NAT, entrambi tentando di inviare dallo stesso numero di porta.
Trevor Powell,

Ah, beh, stavo solo pensando che l'IP stesso dovrebbe essere preso in considerazione. La porta non ha molta importanza; È solo per impedire a una terza parte malintenzionata di rubare il token e utilizzarlo altrove. Non importa se ci sono più utenti dietro lo stesso NAT, poiché il token identificherà l'utente reale, quindi non ci sono problemi di collisione di cui preoccuparsi.
Kaslai,

2

Il client dovrebbe avere una chiave privata e una pubblica .

La chiave privata dovrebbe essere l'identificatore univoco che il client riceve dal server di autenticazione. La chiave pubblica deve essere inviata anche al client.

Prima che il client si connetta a un server di gioco, deve inviare un messaggio con la sua chiave privata e l'ip del server di gioco a cui desidera connettersi al server di autenticazione. Il server di autenticazione dovrebbe quindi verificare e trovare la corrispondenza per la chiave privata e archiviare la chiave pubblica nei suoi record.

Il server di gioco a cui si sta connettendo il client dovrebbe inviare una richiesta al server di autenticazione dopo aver ottenuto la chiave pubblica del client. Se il server di autenticazione è in grado di verificare che il client desideri connettersi a quell'indirizzo IP del server di gioco, invia che è un client a posto. Il server di gioco dovrebbe quindi consentire al client di connettersi.

La chiave privata viene utilizzata solo per l'autenticazione del client in modo che il server di gioco non ottenga il vero ID di autenticazione.


1
Penso di capire il processo utilizzato. Ho scritto una specie di diagramma di flusso: i.pyratron.com/MXkZXU.png Queste informazioni sembrano corrette?
Cyral

@Cyral Sembra corretto.
Statico

1

Ci sono diverse soluzioni che mi vengono in mente, ma qui è la più sicura:

  1. il client si collega al server.
  2. il client richiede un bridge di autenticazione.
  3. il server si connette al server auth, fungendo da proxy tra player e auth. server.
  4. client e server di autenticazione, formano una sessione SSL su questo bridge appena formato.
  5. usando questa connessione sicura su bridge, il client accede al server di autenticazione.
  6. Il server auth indica al server di gioco se l'accesso ha avuto esito positivo o meno, tramite un'altra connessione TCP. quindi disconnette la connessione bridge / login.
  7. il client e il server di gioco possono ora riprendere la comunicazione (solo) tramite una connessione già esistente (utilizzata per l'autenticazione).

Si noti che, in questo scenario, il server di gioco in realtà non ha modo di intercettare, anche se l'intera autenticazione lo sta attraversando. per lo stesso motivo il tuo ISP non può monitorare quali pacchetti invii a Facebook o provengono da Facebook.


Tecnicamente l'ISP ha accesso ai dati grezzi.
Statico

@HaroldSeefeld Tecnicamente non quelli che passano attraverso la connessione IPSec / HTTPS.
Ali1S232,

1

Il modo in cui lo farei è fare in modo che il server Auth invii il token al client dopo il login insieme all'elenco dei server di gioco convalidati (in modo che il client possa essere sicuro che il server di gioco sia valido).

Quindi il client invia il token al server di gioco, che lo invia al server Auth per confermare che si tratta del client valido.

Accesso:

  1. Da client a server Auth: nome utente e password crittografata
  2. Server di autenticazione al client: token

Più tardi quando ti unisci a un server di gioco:

  1. Da client a server di gioco: il token menzionato in precedenza
  2. Server di gioco su server Auth: di nuovo il token
  3. Server di autenticazione su server di gioco: se il token è valido, allora segnale OK
  4. Game server to Client: consente al client di unirsi

0

Che ne dite di firmare un token JWT con un segreto che solo l'autorità centrale e il server del giocatore conoscono? Ti consente di firmare json, che può essere verificato in seguito.


Ciò non consentirebbe ai server gestiti dai giocatori di rubare le credenziali dei loro utenti?
idbrii,

No, 2 modi per farlo: 1 - il client richiede un jwt con il server in esso, consentendo al server di rubare l'identità, ma solo sul proprio server (non un grosso problema) 2 - JWT funziona solo una volta
Ben Aubin,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.