Un record di disconnessione arriva dopo che una seconda connessione con lo stesso nome è già iniziata, e un gestore che aggiorna la riga più recente per quell’utente chiude la sessione sbagliata. L’errore non è il confronto dei timestamp. È l’assunto che un nome più un secondo intero identifichino una sessione. Gli eventi hook descrivono connessioni, e una connessione ha bisogno di una chiave che appartenga solo a lei.

Cominciate da ciò che significano davvero le variabili di disconnessione. Solo allora la scelta dell’identificatore ha senso.

Che cosa trasporta davvero l’hook di disconnessione

In Community OpenVPN 2.6, il riferimento degli hook time_unix lo definisce come il momento in cui il client si è connesso; viene impostato prima che l’hook di connessione venga eseguito e non viene ridefinito quando l’hook di disconnessione scatta più tardi. time_duration fornisce la durata di quella sessione in secondi, quindi la fine è all’incirca l’ora di connessione più la durata. Entrambi sono secondi interi, e nessuno dei due è il momento in cui il vostro database ha elaborato l’evento. È tenere separati questi tre tempi che fa reggere una correlazione, invece di farla solo sembrare corretta durante i test.

Quest’aritmetica merita di essere scritta, perché è l’unico orario di fine che l’hook stesso offre. Il ritardo di elaborazione e le differenze di orologio tra host restano comunque fuori.

Perché la coppia ovvia non è unica

Accoppiare il nome con l’ora di connessione restringe la ricerca e ancora non identifica una sessione. Un client può riconnettersi nello stesso secondo, quindi due sessioni possono condividere entrambi i valori. Due istanze del demone, o una sostituzione del server che mantiene la stessa configurazione, possono produrre quella coppia da processi diversi. Gli indirizzi del tunnel vengono riciclati per lo stesso motivo, il che li rende attributi di una sessione anziché identificatori di essa.

La modalità di guasto è silenziosa. Una disconnessione tardiva della prima sessione corrisponde alla riga più recente e ritira un’allocazione che la seconda sessione sta ancora usando, così l’utente subisce una perdita di accesso casuale che non ha causato. Un conteggio di righe che dopo sembra corretto rende il problema più difficile da individuare.

Da dove viene un’identità stabile

L’interfaccia di gestione assegna a ogni client un identificatore di istanza client, e quell’identificatore è limitato all’istanza del demone che lo ha emesso. Una chiave esterna utilizzabile combina un identificatore di server stabile, un’epoca che cambia all’avvio del demone e quell’ID client. L’epoca conta perché gli identificatori ripartono con il processo, e un semplice ID di processo può essere riutilizzato più tardi da qualcosa di non correlato.

Le variabili d’ambiente impostate dentro uno script di connessione figlio non viaggiano verso lo script di disconnessione successivo del demone padre, perché quegli script vengono eseguiti come processi separati con i propri ambienti. Generare un UUID al momento della connessione è quindi mezza soluzione. Il lato della disconnessione deve poter nominare lo stesso UUID, il che significa che l’identità deve vivere in un luogo che entrambi gli eventi possono raggiungere.

Rendete il ritiro condizionale e idempotente

Ritirate per proprietario della sessione, non per utente. Un gestore che elimina qualsiasi allocazione che attualmente appartiene a un nome finirà per eliminare quella sbagliata, e l’unica difesa è verificare che il record rimosso sia il record che questo evento descrive.

L’interfaccia di gestione accetta un solo client di gestione connesso alla volta, quindi integratevi con chi la possiede già invece di collegare un secondo osservatore che compete per lo stesso socket.

Gestite gli eventi ripetuti senza cambiare il risultato due volte, e conservate gli eventi non appaiati per la riconciliazione invece di scartarli. Una callback di disconnessione ha condizioni del ciclo di vita documentate e può non arrivare mai dopo un crash o un arresto forzato, quindi il progetto ha bisogno di un modo per rappresentare una sessione il cui evento finale manca.

Provate i casi scomodi di proposito: due riconnessioni nello stesso secondo, due istanze del demone, una connessione la cui elaborazione è fallita e un riavvio del demone a metà di una sessione. Una chiave che sopravvive a tutti e quattro è una chiave degna di fiducia.

Articoli correlati