Approccio per autenticare i client sul server TCP

1

Sto scrivendo un'applicazione server / client in cui i client si connetteranno al server. Quello che voglio fare è assicurarsi che il client che si connette al server stia effettivamente usando il mio protocollo e io possa "fidarmi" dei dati inviati dal client al server.

Ciò che ho pensato di fare è creare una sorta di hash sulla macchina del client che segue un particolare algoritmo. Quello che ho fatto in una versione precedente è stato il loro indirizzo IP, la versione client e alcuni altri attributi del client e l'ho inviato come un hash calcolato al server, che poi ha preso il loro IP e la versione del protocollo il client ha affermato di utilizzare e ha calcolato quel numero per vedere se corrispondevano. Funziona bene fino a quando non si ottengono client che si connettono da un ambiente router in cui il loro IP interno è diverso dal loro IP esterno. La mia correzione per questo era passare l'IP interno del client usato per calcolare questo hash con il protocollo di autenticazione. La mia paura è che questo approccio non è abbastanza sicuro. Poiché sto passando i dati utilizzati per creare "auth hash".

Ecco un esempio di ciò di cui sto parlando:

Client IP: 192.168.1.10, Version: 2.4.5.2
hash = 2*4*5*1 * (1+9+2) * (1+6+8) * (1) * (1+0)
Client Connects to Server
client sends: auth hash ip version
Server calculates that info, and accepts or denies the hash.

Prima di andare a inventare un altro algoritmo per dimostrare che un client può fornire dati a un server (o utilizzare questo algoritmo esistente), mi chiedevo se esistessero sistemi esistenti, provati e sicuri per generare un hash che entrambe le parti possono generare con la conoscenza generale. Il server non conoscerà il client fino a quando non viene stabilita la prima connessione.

L'intento del protocollo è di gestire una rete di clienti che contribuiranno periodicamente con i dati del server.

I nuovi client verranno aggiunti semplicemente collegando il client al server e "registrandosi" con il server. Quindi un client si connette al server per la prima volta e registra le proprie informazioni (indirizzo mac o qualche altro tipo di identificatore univoco del computer), quindi quando si connettono di nuovo, il server riconoscerà quel client come una persona precedente e li assocerà al loro dati nel database.

Modifica: L'approccio alla fine è stato questo:

Ho finito per utilizzare un approccio simile a quello che OpenSSH fa, ma invertire. Da quando un client si connette, non sono sicuro di potermi fidare del client.

Se è la prima volta che un client si connette, mi fornirà una chiave pubblica e un identificatore univoco (In questo caso, userò il tag di servizio di un computer dato che i computer con cui ho a che fare saranno sono tutti Dells). Il server memorizza l'id e la chiave pubblica nel database, quindi invia al client una domanda segreta crittografata utilizzando la chiave pubblica. Il cliente dovrà quindi rispondere con la risposta decrittografata. Prima che un client possa essere accettato dal server, potrei finire a fare una registrazione id univoca sul server manualmente prima di connettere il client per la prima volta, in questo modo nessuna persona sorniona può solo generare chiavi pubbliche ed emulare ciò che fa un client un "nuovo ID unico".

Grazie per l'aiuto! Spero che questo aiuti qualcuno in prima linea. Sentiti libero di distruggere i difetti di sicurezza di questo approccio:)

    
posta dab 05.11.2013 - 21:16
fonte

1 risposta

3

Non puoi davvero fare l'autenticazione senza condividere nulla prima mano. Se puoi avere qualsiasi tipo di segreto condiviso (es. Una chiave), puoi usare l'autenticazione challenge-response utilizzando un appropriato algoritmo di digest del messaggio.

Sul tema della compatibilità del protocollo, vorrei separare le preoccupazioni. Puoi utilizzare un tradizionale handshake per verificare che il cliente stia parlando dello stesso protocollo / versione utilizzata dal server (o di uno compatibile), ma l'autenticazione viene gestita separatamente separatamente.

Un'alternativa con un compromesso accettabile in molti sistemi distribuiti è affidarsi alla prima connessione da un client specifico, condividere una chiave e quindi convalidare tutte le connessioni successive dallo stesso client che lo utilizza. Questo è ciò che OpenSSH fa quando si connette a un nuovo server (richiede se si desidera connettersi a un host sconosciuto e quindi memorizzare l'impronta digitale di quell'host e convalidarlo nelle connessioni successive). Puoi trovare una spiegazione più dettagliata del meccanismo "host conosciuti" di SSH nella wiki di WinSCP .

Puppet utilizza una variante di questo in cui hanno un certificato SSL firmato (attendibile) su ciascun client. Quando si collega per la prima volta un agente al server, l'agente emetterà una richiesta di firma del certificato per il server che dovrà quindi firmare manualmente e consegnarla all'agente. Ciò ha aggiunto sicurezza, ma può diventare fastidioso rapidamente se è necessario impostare molti client o farlo senza che nessuno interagisca con il sistema. Questo è il motivo per cui esiste un'opzione di configurazione che modifica il comportamento in modo che sia simile a SSH (si consideri attendibile chiunque non l'abbia mai visto prima, convalidare le identità solo per gli host conosciuti). Questo è descritto in maggior dettaglio nel sito web di PuppetLabs .

Alla fine, quello che hai è un problema di fiducia. La domanda rimane: come puoi fidarti di una connessione da un client? La risposta a questo non è di natura tecnica - accettare qualsiasi nuova connessione da parte di un host sconosciuto e fidarsi ciecamente potrebbe funzionare per alcuni sistemi, ma non per tutti. Dipende davvero dai compromessi del sistema attuale che stai implementando e dalle capacità concesse al client dal server.

    
risposta data 05.11.2013 - 21:24
fonte

Leggi altre domande sui tag