2010-05-11 18 views
7

Ho creato un'applicazione utilizzando UDP per trasmettere e ricevere informazioni. Il problema che sto incontrando è la sicurezza. In questo momento sto usando l'IP/socketid nel determinare quali dati appartengono a chi.Protezione UDP e identificazione dei dati in entrata

Tuttavia, ho letto su come le persone potrebbero semplicemente falsificare il loro IP, quindi semplicemente inviare dati come un IP specifico. Quindi questo sembra essere il modo sbagliato di farlo (insicuro). Quindi, in quale altro modo dovrei identificare quali dati appartengono a quali utenti? Ad esempio, hai 10 utenti connessi, tutti hanno dati specifici. Il server dovrebbe abbinare i dati dell'utente a questi dati che abbiamo ricevuto.

L'unico modo che posso vedere per fare ciò è utilizzare una sorta di sistema di chiavi client/server e crittografare i dati. Sono curioso di sapere come altre applicazioni (o giochi, dato che è questa l'applicazione) assicurano che i loro dati siano autentici. Inoltre, il processo di crittografia richiede molto più tempo rispetto a quello non criptato. Anche se non sono sicuro di quanto influirà sulle prestazioni.

Qualsiasi informazione sarebbe apprezzata. Grazie.

+0

Si potrebbe voler considerare una sorta di tunneling come SSH o IPSEC. L'unico modo per affermare chi è chi è per mezzo dell'autenticazione. – jathanism

+0

@jathanism Che dire di Lag? E cosa è sbagliato ssl/tls/dtls? – rook

+0

Non c'è niente di sbagliato con SSL/TLS/DTLS, stavo solo offrendo alternative. In particolare, SSL richiede certificati firmati, a meno che non si utilizzino certificati autofirmati, quindi in realtà non si compra molto se non per la crittografia. – jathanism

risposta

1

Potete guardare HMAC

Wikipedia:

In crittografia, HMAC (Hash-based Message Authentication Code), è una costruzione specifica per il calcolo un codice di autenticazione del messaggio (MAC) che comprende una funzione di crittografia hash in combinazione con una chiave segreta . Come con qualsiasi MAC, può essere utilizzato per verificare contemporaneamente l'integrità dei dati e l'autenticità di un messaggio .

Ogni cliente dovrebbe ottenere un token univoco che solo loro conoscono. Ogni messaggio che inviano, eseguirà un hash basato sul token e sul messaggio e lo invierà insieme al messaggio stesso. Quindi è possibile verificare che il messaggio provenga da un cliente specifico.

+0

HMAC è per l'integrità dei dati, non ho capito come impedisce lo spoofing IP? – berkay

+0

+1: una sfida/risposta all'avvio della sessione, quindi ogni messaggio avrebbe una firma su (data + chiave di sessione) aggiunta – Robert

+0

@Berkay: è quasi impossibile che lo spoofer "conosca" il seme del client (utilizzato per calcolare il HMAC), in modo che il server possa abbandonare in modo sicuro tutti i messaggi senza un HMAC positivo. – Robert

0

Se è assolutamente necessario verificare che un determinato utente sia un determinato utente, è necessario utilizzare una qualche forma di crittografia in cui l'utente firma i propri messaggi. Questo può essere fatto abbastanza rapidamente perché l'utente deve solo generare un hash del proprio messaggio e quindi firmare (crittografare) l'hash.

Per la tua applicazione di gioco probabilmente non devi preoccuparti di questo. La maggior parte degli ISP non consente agli utenti di falsificare gli indirizzi IP, pertanto è necessario preoccuparsi solo degli utenti che stanno dietro NAT in cui è possibile che più utenti eseguano dallo stesso indirizzo IP. In questo caso, e in generale, è possibile identificare in modo abbastanza sicuro gli utenti unici sulla base di una tupla contenente l'indirizzo IP e la porta UDP.

+0

Il punto di udp è leggero. L'uso della crittografia aumenterebbe significativamente il sovraccarico del protocollo rispetto al TCP che è immune allo spoofing. – rook

+1

Non sono d'accordo. Il punto di UDP è in tempo reale piuttosto che affidabile. In un ambiente di gioco ti importa meno dell'affidabilità e più della bassa latenza. Il sovraccarico di mettere i pacchetti in ordine è principalmente dovuto ai tempi di andata e ritorno della rete, non al codice extra nello stack TCP. Inoltre, ipotizzo il calcolo di un hash su un datagramma e il calcolo di una firma per esso non introduce un collo di bottiglia rispetto alle latenze medie di Internet. – bboe

+0

L'uso di un codice di flusso con udp consente di risparmiare alcuni bit di larghezza di banda rispetto al TCP. Tuttavia, in generale, credo che questo sistema di sicurezza intenzionale stia abusando delle risorse. Soprattutto le risorse dello sviluppatore per implementare questo sistema di sicurezza mirato. SSL/TLS è una soluzione gratuita e la più sicura a questo problema. – rook

4

Una soluzione è quella di utilizzare il protocollo TCP, perché è immune da spoofing l'indirizzo sorgente su internet aperta a causa del three-way-handshake (More information sul motivo per cui indirizzo sorgente TCP spoofing è impossibile.). Se si desidera ancora utilizzare UDP, è possibile simulare un handshake a tre vie per iniziare la connessione. Un id di sessione potrebbe quindi essere aggiunto a ciascun pacchetto UDP. Ciò aumenterà il sovraccarico della connessione di 2 pacchetti e alcuni bit per pacchetto, tuttavia continuerai a guadagnare dalla velocità di UDP per il resto della sessione rispetto a TCP.

Tuttavia, utilizzando il protocollo TCP o UDP come transport layer lascia ancora aperto ad altri attacchi come Sniffing e Man in The Middle attacchi utilizzando arp spoofing o dns cache poising. Un altro problema è se sia l'attaccante che i giocatori si trovano sulla stessa LAN locale, come una rete wireless o un'altra rete di trasmissione, quindi si può ricevere traffico indipendentemente dall'indirizzo di origine/destinazione e SOLO ALLORA fa uno spoofing a tre vie la stretta di mano diventa possibile (e un hmac non può aiutare!). La soluzione migliore è utilizzare SSL/TLS come livello di trasporto che risolve tutti questi problemi.

Non si deve reinventare il pomfo, ma se avete bisogno di crittografare UDP per qualche motivo si dovrebbe usare un cifrario a flusso, come RC4-drop1024 o meglio ancora un cifrario a blocchi come AES 256 in OFB Mode. Ciò consentirà di risparmiare larghezza di banda rispetto ad altre modalità di crittografia poiché arrotondano alla dimensione massima del blocco.

EDIT: Sulla base di Marts commento per (Datagram Transport Layer Security) DTLS ho fatto qualche scavo e ho trovato c'è un official RFC e la sua supportato da OpenSSL e deve essere esposto utilizzando la libreria pyOpenSSL. Raccomando di usare la suite di crittografia RC4-SHA per ridurre il sovraccarico, questa suite è supportata da SSL 3.0 (più recente). Tuttavia DTLS probabilmente avrà più overhead (LAG!) Quindi TCP.

+0

Per UDP, la soluzione utilizza DTLS, non reinventando la ruota utilizzando direttamente i chiphers. Considerando la domanda originale, il poster originale probabilmente non riuscirà a farlo bene la prima volta. –

+0

@Mart Oruaas Cool non sapevo di DTLS, se è stato creato da TLS dovresti essere in grado di negoziare l'uso di un codice di streaming con larghezza di banda. – rook

+0

Ho esaminato il TCP e sembra una buona scelta per evitare quello che sto chiedendo. Tuttavia molti articoli che ho letto lo scoraggiano dai giochi. Tecnicamente non è possibile falsificare anche un ID di sessione? Basta inviare pacchetti aumentando il numero # fino a quando non si ottiene una risposta che funziona? Guarderò i Cipher come sembrano interessanti. Una cosa da notare per gli altri è che i dati del client devono essere letti e utilizzati in qualche modo. Pertanto l'hashing dei dati non funzionerà. Aggiungendo un hash alla parte anteriore dei dati si aumenterebbe la dimensione dei dati a livelli insopportabili. – Charles

0

DTLS è probabile che la soluzione migliore , tuttavia, sembra essere molto scarsamente documentata. Ho cercato una soluzione simile per un po 'di tempo e tutti i riferimenti che ho visto sull'implementazione DTLS di OpenSSL suggeriscono che sarà necessario scavare attraverso il codice sorgente degli esempi OpenSSL & per capire come usarlo. .. che, per me, significa che farò 10 seri errori di sicurezza quando cerco di configurarlo. Inoltre, non credo che il liberatore pyOpenSSL esporti questa funzionalità.

Un'alternativa che ho preso in considerazione è la Secure Remote Password Protocol. Il vantaggio di questa soluzione è che ti dà una forte autenticazione reciproca (alla pari con la sicurezza di Kerberos secondo i documenti) e, altrettanto importante nel tuo caso, fornisce entrambe le estremità con una chiave di sessione condivisa che può essere utilizzata per la crittografia .

Data la chiave condivisa, ogni pacchetto può contenere AES256_CBC(<random starter block for CBC><user-id><sequence_number><application data>) Se la decrittografia riesce a fornire l'id utente previsto, il pacchetto viene autenticato come proveniente dal proprio utente e il numero di sequenza può essere utilizzato per evitare attacchi di riproduzione.

Uno svantaggio di SRP è che, in Python, il numero di crunch è piuttosto lento. Ho modificato il codice demo Python in qualcosa di un po 'più utilizzabile e ho scoperto che ci sono voluti circa 300ms per eseguire un singolo scambio SRP client-server (CPU 2Ghz). Tuttavia, un'implementazione diretta in C++ dell'algoritmo SRP che utilizzava il supporto di BigNumber in OpenSSL richiedeva solo 2 ms. Quindi, se intendi seguire questa strada, ti consiglio vivamente di utilizzare un'implementazione C/C++ dell'algorihim per il codice di produzione. Altrimenti, probabilmente sarai in grado di gestire solo pochi accessi al secondo.

+0

Questo sistema di sicurezza è molto vicino a quello che ho detto, tranne che hai tralasciato la parte più importante in quanto tutto questo aggiunge ** GAL **. L'attacco è quello di fermare lo spoofing, non facilitando la caduta. – rook

+0

@Rook: non proprio. Questo è un approccio specifico per proteggere la comunicazione UDP usando un protocollo standard per l'autenticazione e lo scambio di chiavi. Lo spoofing e l'intercettazione sono impediti con questo approccio e non vi è alcun ritardo indotto al di fuori dell'handshake di autenticazione iniziale. – Rakis

0

Sto suddividendolo in quattro livelli di sicurezza.

  • Estremamente insicuro - Chiunque sulla rete può eseguire lo spoofing di una richiesta/risposta valida con conoscenze preliminari generalmente disponibili. (es. syslog)

  • Molto insicuro: chiunque nella rete può inviare una richiesta/risposta valida solo se ha almeno accesso in lettura al filo.(Passive MITM) (ad esempio, forum accessibile http con i cookie del browser)

  • Un po 'insicuro: chiunque nella rete può falsificare una richiesta/risposta valida se è in grado di leggere E apportare modifiche al cavo (Active MITM) (cioè sito https con certificato autofirmato)

  • Sicuro: le richieste/risposte non possono essere falsificate nemmeno con l'accesso completo al filo . (Ovvero https accessibile sito e-commerce)

Per i giochi di Internet la soluzione molto insicuro potrebbe in realtà essere accettabile (sarebbe la mia scelta) Non richiede crypto. Solo un campo nel formato di pacchetto UDP delle app con qualche tipo di identificatore di sessione casuale praticamente indecifrabile effettuato in giro per la durata del gioco.

Un po 'insicuro richiede un po' di crittografia, ma nessuno dei trust/PKI/PSK necessari per prevenire Active-MITM della soluzione sicura. Con un po 'di insicurezza se i payload dei dati non erano sensibili, si poteva usare un algoritmo di sola integrità con DTLS (TCP) TLS/(UDP) per ridurre il sovraccarico di elaborazione e la latenza sul client e sul server.

Per i giochi UDP è un vantaggio enorme perché se c'è perdita di pacchetti non si desidera che lo stack IP sprechi tempo a ritrasmettere lo stato vecchio: si desidera inviare un nuovo stato. Con UDP ci sono una serie di schemi intelligenti come frame non riconosciuti (dettagli del mondo che non contano molto se perduti) e metodi statistici di duplicazione di dati importanti dello stato per contrastare i livelli prevedibili di perdita di pacchetti osservati.

Alla fine della giornata, mi sento di raccomandare solo l'integrità DTLS molto insicura o alquanto insicura.

0

Vorrei esaminare la libreria di rete di Garage Games. È scritto in C++ e usa UDP. È progettato per una bassa latenza ed è considerato uno dei migliori per i giochi.

Se ricordo bene, in realtà calcolerebbero la probabile posizione del giocatore sia sul lato client che sul lato server. Lo farebbe per molti aspetti per garantire l'integrità dei dati. Effettua anche un controllo crc sul software client e lo confronta con il software server per assicurarsi che corrisponda.

Non sono sicuro che sia possibile effettuare la licenza separatamente, quindi è possibile che sia necessario concedere in licenza il motore di gioco (100 dollari). Vi darebbe almeno qualche informazione su un approccio collaudato all'UDP per i giochi. Un'altra possibilità è quella di esaminare il codice di rete PyGame. Potrebbe aver già affrontato i problemi che stai affrontando.

Problemi correlati