Dove appartiene una quota mensile di dati per account OpenVPN
Una quota che si azzera a ogni riconnessione non è un limite. Segui l’uso per account, addebita ogni delta di byte una sola volta e fai sì che l’esaurimento blocchi l’ammissione.
Una quota che si azzera ogni volta che il tunnel si riconnette non è un limite, ed è esattamente ciò che si ottiene quando un contatore di byte viene avvitato a un server VPN senza un posto dove conservare stato durevole. Il contatore appartiene a una sessione; la quota appartiene a una persona o a un contratto di dispositivo. Tutta la difficoltà della funzione nasce da questo disallineamento, quindi i controlli qui sotto riguardano dove vive lo stato e quale strato può decidere.
Fissa la quota a un account, non a un tunnel
Comincia dando un nome al soggetto della quota. Una persona può avere tre certificati di dispositivo, e nessuno di essi dovrebbe ricevere un budget mensile indipendente solo perché si autenticano separatamente. Un identificatore di account stabile che sopravvive a riconnessioni, nuovi indirizzi di tunnel e un trasloco su un secondo gateway è l’unico ancoraggio che una quota può usare. Il nome comune di un certificato funziona come quella chiave solo se la tua politica di emissione garantisce un account per nome.
Un indirizzo di tunnel assegnato non è mai la risposta. Gli indirizzi vengono riciclati, i pool sono condivisi, e lo stesso account può comparire due volte su due gateway nello stesso minuto. Se il registro si basa su un indirizzo, disconnettersi e riconnettersi basta a riempire di nuovo il serbatoio.
Registra abbastanza per sessione perché l’aritmetica sia verificabile: l’account, il periodo di fatturazione, l’istanza del gateway, l’identità di sessione, gli ultimi contatori osservati e il totale impegnato. Includi una generazione di avvio del demone nell’identità di sessione, perché un server riavviato riusa gli ID client e una corrispondenza ingenua erediterebbe la linea di base precedente.
Fissa l’unità, la direzione e il confine di azzeramento
Quattro definizioni vanno stabilite per iscritto prima che inizi qualsiasi raccolta. La quota conta i byte che il client invia, quelli che riceve, o la somma dei due? Un gigabyte è 10^9 byte o 2^30? A quale ora locale e in quale fuso orario il periodo si azzera? E che cosa misura esattamente il contatore, dato che l’overhead del tunnel e le ritrasmissioni sono inclusi mentre la dimensione del file dell’applicazione e la fattura di un fornitore non lo sono?
Nessuna di queste scelte è sbagliata, ma l’implementazione e il numero che il cliente vede devono coincidere. Due metà dello stesso sistema in disaccordo su GiB, o su un azzeramento che avviene a mezzanotte UTC invece che all’ora locale, producono esattamente il tipo di ticket che erode la fiducia nell’intera quota.
Trasforma i totali di byte in un solo delta addebitato
L’interfaccia di gestione riporta righe BYTECOUNT_CLI periodiche che portano un ID client più totali cumulativi di byte in ciascuna direzione, e il comando bytecount stabilisce con quale frequenza arrivano. Dal punto di vista del server, la cifra ricevuta conta i byte inviati dal client e la cifra inviata conta i byte consegnati a esso. Imposta l’intervallo su qualcosa che il registro possa assorbire; un intervallo molto breve compra una precisione che in realtà non ottieni.
Un vincolo dà forma all’intero progetto: il socket di gestione accetta una sola connessione di controllo. Un esportatore di monitoraggio, una GUI e il tuo controller non possono aprirne ciascuno la propria. Decidi quale processo possiede il canale e lascia che gli altri leggano lo stato da esso, perché questa interfaccia concede azioni amministrative e comunque non dovrebbe essere esposta fuori dall’host.
rx_delta = sample.rx_now - session.prev_rx
tx_delta = sample.tx_now - session.prev_tx
charge = rx_delta + tx_delta
# same transaction:
ledger.total += charge
session.prev_rx, session.prev_tx = sample.rx_now, sample.tx_now
Impegna insieme le nuove linee di base e l’incremento di utilizzo, così che ripetere un campione non addebiti nulla invece di addebitare due volte. Un contatore che torna indietro è un segnale, non un debito: significa che la sessione è stata sostituita o che il demone è stato riavviato, e la risposta corretta è riconciliare l’identità di sessione invece di accreditare un importo negativo.
Il percorso di disconnessione richiede la stessa cura. Se un evento finale porta totali di fine sessione, addebita solo la differenza rispetto all’ultimo campione impegnato. Aggiungere il totale completo dopo che il campionamento periodico è già stato addebitato è il doppio conteggio più comune nei sistemi di quota fatti in casa. Anche le sessioni che attraversano un confine di periodo hanno bisogno di una regola, poiché un solo totale finale non porta alcuna informazione su quando i byte hanno superato la mezzanotte.
Fai sì che l’esaurimento neghi l’ammissione, non solo uccida il tunnel
Quando un account raggiunge il suo limite, devono accadere due cose: le sessioni esistenti finiscono e le nuove vengono rifiutate. Il protocollo di gestione fornisce client-kill per ID client, che risolve la prima metà purché tu enumeri ogni sessione viva dell’account invece di uccidere l’unico indirizzo che ti è capitato di notare.
La seconda metà è dove i progetti di quota falliscono. Un solo kill è una corsa contro il ciclo di riconnessione del client, che tornerà volentieri pochi secondi dopo. L’ammissione deve consultare il registro condiviso, e in un deployment multi-gateway quel controllo non può essere un file per macchina. Ogni istanza che può accettare un login deve vedere lo stesso stato esaurito.
Le riconnessioni basate su token meritano un proprio test. OpenVPN 2.6 può validare un token di sessione internamente con auth-gen-token, saltando la chiamata di autenticazione esterna che il tuo controller usava per imporre il tetto. Un token ancora valido dimostra quindi l’identità, non la quota residua, e ogni nuova istanza client deve comunque consultare il registro. Se invece abiliti management-client-auth, il controller diventa l’autenticatore ed eredita l’obbligo di analizzare da sé lo stato della sessione e di rifiutare token scaduti o non validi.
Accetta il superamento che il campionamento crea
L’osservazione periodica più la disconnessione ti danno una quota campionata con una tolleranza nota. Un client può superarla di circa un intervallo di rendicontazione più il tempo che il controller impiega ad agire, e le sessioni concorrenti su un account moltiplicano quella finestra. Dillo nell’interfaccia invece di annunciare un taglio esatto all’ultimo byte che non puoi fornire.
Un vero tetto rigido è un altro problema di ingegneria: applicazione dentro il percorso di inoltro, legata allo stesso account attraverso le sessioni. Leggere i contatori più in fretta non è la stessa cosa, e non sopravvive a un client che semplicemente apre più tunnel.
Prima del rilascio, esegui i casi di accettazione che rompono le implementazioni ingenue: riconnessioni ripetute, due dispositivi insieme, riavvii di controller e gateway, un evento di disconnessione perso, un azzeramento a metà sessione e un tentativo di riconnessione con token subito dopo l’esaurimento. Poi decidi la modalità di guasto per le interruzioni della contabilità. Un registro durevole protegge l’uso che hai registrato; non può resuscitare osservazioni che non sono mai arrivate, e il cliente merita di sapere in quale di queste due situazioni si trova.