Passa al contenuto principale

3. Protocollo di Tempo di Rete

Questa sezione consiste in una definizione formale del Protocollo di Tempo di Rete, inclusi i suoi formati di dati, entità, variabili di stato, eventi e procedure di elaborazione degli eventi. La specifica si basa sul modello di implementazione illustrato nella Figura 1, ma non è inteso che questo modello sia l'unico su cui può essere basata una specifica. In particolare, la specifica è destinata a illustrare e chiarire le operazioni intrinseche di NTP, nonché a servire come fondamento per una specifica più rigorosa, completa e verificabile.

3.1. Formati dei Dati

Tutte le operazioni matematiche espresse o implicite qui sono in aritmetica a virgola fissa in complemento a due. I dati sono specificati come quantità intere o a virgola fissa, con bit numerati in modo big-endian da zero partendo dalla posizione sinistra o di ordine superiore. Poiché varie implementazioni possono scalare quantità derivate esternamente per uso interno, né la precisione né il posizionamento del punto decimale per quantità a virgola fissa sono specificati. Salvo diversa indicazione, tutte le quantità sono senza segno e possono occupare l'intera larghezza del campo con uno zero implicito che precede il bit zero. I pacchetti hardware e software progettati per funzionare con quantità con segno produrranno quindi risultati sorprendenti quando il bit più significativo (segno) è impostato. Si suggerisce che le quantità a virgola fissa senza segno derivate esternamente come i timestamp vengano spostate di un bit a destra per uso interno, poiché la precisione rappresentata dall'intera larghezza del campo è raramente giustificata.

Poiché i timestamp NTP sono dati preziosi e, di fatto, rappresentano il prodotto principale del protocollo, è stato stabilito un formato di timestamp speciale. I timestamp NTP sono rappresentati come un numero a virgola fissa senza segno a 64 bit, in secondi relativi alle 0h del 1 gennaio 1900. La parte intera è nei primi 32 bit e la parte frazionaria negli ultimi 32 bit. Questo formato consente un'aritmetica multi-precisione conveniente e la conversione in rappresentazione del Protocollo di Tempo (secondi), ma complica la conversione in rappresentazione del messaggio di timestamp ICMP (millisecondi). La precisione di questa rappresentazione è di circa 200 picosecondi, che dovrebbe essere adeguata anche per i requisiti più esotici.

I timestamp sono determinati copiando il valore corrente dell'orologio locale in un timestamp quando si verifica un evento significativo, come l'arrivo di un messaggio. Per mantenere la massima accuratezza, è importante che questo sia fatto il più vicino possibile al driver hardware o software associato all'evento. In particolare, i timestamp di partenza dovrebbero essere rideterminati per ogni ritrasmissione a livello di collegamento. In alcuni casi un particolare timestamp potrebbe non essere disponibile, ad esempio quando l'host viene riavviato o il protocollo si avvia per la prima volta. In questi casi il campo a 64 bit è impostato su zero, indicando che il valore è non valido o non definito.

Si noti che da un certo momento nel 1968 il bit più significativo (bit 0 della parte intera) è stato impostato e che il campo a 64 bit traboccherà in un certo momento nel 2036. Se NTP sarà in uso nel 2036, saranno necessari mezzi esterni per qualificare il tempo relativo al 1900 e il tempo relativo al 2036 (e altri multipli di 136 anni). I dati con timestamp che richiedono tale qualificazione saranno così preziosi che mezzi appropriati dovrebbero essere facilmente disponibili. Esisterà un intervallo di 200 picosecondi, d'ora in poi ignorato, ogni 136 anni quando il campo a 64 bit sarà zero e quindi considerato non valido.

3.2. Variabili di Stato e Parametri

Quello che segue è un riepilogo delle varie variabili di stato e parametri utilizzati dal protocollo. Sono separati in classi di variabili di sistema, che si riferiscono all'ambiente del sistema operativo e al meccanismo dell'orologio locale; variabili di peer, che rappresentano lo stato della macchina di protocollo specifica per ciascun peer; variabili di pacchetto, che rappresentano il contenuto del messaggio NTP; e parametri, che rappresentano costanti di configurazione fisse per tutte le implementazioni della versione corrente. Per ciascuna classe, la descrizione della variabile è seguita dal suo nome e dalla procedura o valore che la controlla. Si noti che le variabili sono in minuscolo, mentre i parametri sono in maiuscolo. Ulteriori dettagli sui formati e sull'uso sono presentati nelle sezioni e appendici successive.

3.2.1. Variabili Comuni

Le seguenti variabili sono comuni a due o più delle classi sistema, peer e pacchetto. Variabili aggiuntive sono specifiche per il meccanismo di autenticazione opzionale descritto nell'Appendice C. Quando è necessario distinguere tra variabili comuni con lo stesso nome, verrà utilizzato l'identificatore della variabile.

Indirizzo del Peer (Peer Address,peer.peeraddr, pkt.peeraddr), Porta del Peer (Peer Port,peer.peerport, pkt.peerport): Questi sono l'indirizzo Internet a 32 bit e il numero di porta a 16 bit del peer.

Indirizzo dell'Host (Host Address,peer.hostaddr, pkt.hostaddr), Porta dell'Host (Host Port,peer.hostport, pkt.hostport): Questi sono l'indirizzo Internet a 32 bit e il numero di porta a 16 bit dell'host. Sono inclusi tra le variabili di stato per supportare il multi-homing.

Indicatore di Salto (Leap Indicator,sys.leap, peer.leap, pkt.leap): Questo è un codice a due bit che avverte di un imminente secondo intercalare da inserire nella scala temporale NTP. I bit vengono impostati prima delle 23:59 del giorno di inserimento e reimpostati dopo le 00:00 del giorno seguente. Ciò fa sì che il numero di secondi (intervallo di rollover) nel giorno di inserimento venga aumentato o diminuito di uno. Nel caso dei server primari i bit vengono impostati dall'intervento dell'operatore, mentre nel caso dei server secondari i bit vengono impostati dal protocollo. I due bit, bit 0 e bit 1, rispettivamente, sono codificati come segue:

ValoreSignificato
00nessun avviso
01l'ultimo minuto ha 61 secondi
10l'ultimo minuto ha 59 secondi
11condizione di allarme (orologio non sincronizzato)

In tutti i casi tranne la condizione di allarme (11₂), NTP stesso non fa nulla con questi bit, tranne passarli alle routine di conversione del tempo che non fanno parte di NTP. La condizione di allarme si verifica quando, per qualsiasi motivo, l'orologio locale non è sincronizzato, ad esempio durante il primo avvio o dopo un periodo prolungato in cui nessuna fonte di riferimento primaria è disponibile.

Modalità (Mode,peer.mode, pkt.mode): Questo è un intero che indica la modalità di associazione, con valori codificati come segue:

ValoreModalità
0non specificato
1simmetrico attivo
2simmetrico passivo
3client
4server
5broadcast
6riservato per messaggi di controllo NTP
7riservato per uso privato

Strato (Stratum,sys.stratum, peer.stratum, pkt.stratum): Questo è un intero che indica lo strato dell'orologio locale, con valori definiti come segue:

ValoreSignificato
0non specificato
1riferimento primario (es. orologio atomico calibrato, orologio radio)
2-255riferimento secondario (via NTP)

Ai fini del confronto, un valore di zero è considerato maggiore di qualsiasi altro valore. Si noti che il valore massimo dell'intero codificato come variabile di pacchetto è limitato dal parametro NTP.MAXSTRATUM.

3.2.2. Variabili di Sistema

La Tabella 1 mostra l'insieme completo delle variabili di sistema. Oltre alle variabili comuni descritte in precedenza, le seguenti variabili sono utilizzate dal sistema operativo per sincronizzare l'orologio locale.

Orologio Locale (Local Clock,sys.clock): Questo è il tempo locale corrente, in formato timestamp. Il tempo locale è derivato dall'orologio hardware della macchina particolare e si incrementa a intervalli a seconda del design utilizzato. Un design appropriato, inclusi meccanismi di regolazione e compensazione dello skew, è descritto nella Sezione 5.

Fonte dell'Orologio (Clock Source,sys.peer): Questo è un selettore che identifica la fonte di sincronizzazione corrente. Di solito questo sarà un puntatore a una struttura contenente le variabili del peer. Il valore speciale NULL indica che non c'è attualmente una fonte di sincronizzazione valida.

3.2.3. Variabili del Peer

La Tabella 2 mostra l'insieme completo delle variabili del peer. Oltre alle variabili comuni descritte in precedenza, le seguenti variabili sono utilizzate dalle funzioni di gestione e misurazione del peer.

Bit Configurato (Configured Bit,peer.config): Questo è un bit che indica che l'associazione è stata creata da informazioni di configurazione e non dovrebbe essere smobilitata se il peer diventa irraggiungibile.

Timestamp di Aggiornamento (Update Timestamp,peer.update): Questo è il tempo locale, in formato timestamp, quando è stato ricevuto il messaggio NTP più recente. Viene utilizzato nel calcolo della dispersione dello skew.

Registro di Raggiungibilità (Reachability Register,peer.reach): Questo è un registro a scorrimento di bit NTP.WINDOW utilizzato per determinare lo stato di raggiungibilità del peer, con bit che entrano dall'estremità meno significativa (più a destra). Un peer è considerato raggiungibile se almeno un bit in questo registro è impostato a uno.

Timer del Peer (Peer Timer,peer.timer): Questo è un contatore intero utilizzato per controllare l'intervallo tra i messaggi NTP trasmessi. Una volta impostato su un valore diverso da zero, il contatore decrementa a intervalli di un secondo fino a raggiungere zero, momento in cui viene chiamata la procedura di trasmissione. Si noti che il funzionamento di questo timer è indipendente dagli aggiornamenti dell'orologio locale, il che implica che il sistema di cronometraggio e l'architettura del sistema timer a intervalli devono essere indipendenti l'uno dall'altro.

3.3. Modalità di Operazione

Tranne che in modalità broadcast, un'associazione NTP si forma quando due peer scambiano messaggi e uno o entrambi creano e mantengono un'istanziazione della macchina di protocollo, chiamata associazione. L'associazione può operare in una delle cinque modalità indicate dalla variabile di modalità host (peer.mode): simmetrico attivo, simmetrico passivo, client, server e broadcast, che sono definite come segue:

Simmetrico Attivo (Symmetric Active,1): Un host che opera in questa modalità invia messaggi periodici indipendentemente dallo stato di raggiungibilità o dallo strato del suo peer. Operando in questa modalità, l'host annuncia la sua disponibilità a sincronizzare ed essere sincronizzato dal peer.

Simmetrico Passivo (Symmetric Passive,2): Questo tipo di associazione viene normalmente creato all'arrivo di un messaggio da un peer che opera in modalità simmetrica attiva e persiste solo finché il peer è raggiungibile e opera a un livello di strato inferiore o uguale all'host; altrimenti, l'associazione viene sciolta. Tuttavia, l'associazione persisterà sempre fino a quando almeno un messaggio è stato inviato in risposta. Operando in questa modalità, l'host annuncia la sua disponibilità a sincronizzare ed essere sincronizzato dal peer.

Client (Client,3): Un host che opera in questa modalità invia messaggi periodici indipendentemente dallo stato di raggiungibilità o dallo strato del suo peer. Operando in questa modalità, l'host, solitamente una workstation LAN, annuncia la sua disponibilità ad essere sincronizzato da, ma non a sincronizzare il peer.

Server (Server,4): Questo tipo di associazione viene normalmente creato all'arrivo di un messaggio di richiesta client ed esiste solo per rispondere a quella richiesta, dopo di che l'associazione viene sciolta. Operando in questa modalità, l'host, solitamente un server di tempo LAN, annuncia la sua disponibilità a sincronizzare, ma non ad essere sincronizzato dal peer.

Broadcast (Broadcast,5): Un host che opera in questa modalità invia messaggi periodici indipendentemente dallo stato di raggiungibilità o dallo strato dei peer. Operando in questa modalità, l'host, solitamente un server di tempo LAN che opera su un mezzo broadcast ad alta velocità, annuncia la sua disponibilità a sincronizzare tutti i peer, ma non ad essere sincronizzato da nessuno di essi.

3.4. Elaborazione degli Eventi

Gli eventi significativi di interesse in NTP si verificano alla scadenza di un timer del peer (peer.timer), di cui uno è dedicato a ciascun peer con un'associazione attiva, e all'arrivo di un messaggio NTP dai vari peer. Un evento può verificarsi anche come risultato di un comando dell'operatore o di un guasto di sistema rilevato, come un guasto della fonte di riferimento primaria. Questa sezione descrive le procedure invocate quando si verificano questi eventi.

3.5. Procedura di Distanza di Sincronizzazione

La procedura di distanza calcola la distanza di sincronizzazione dalle variabili del peer per il peer peer.

begin distance(peer) procedure;
DELTA <- peer.rootdelay + |peer.delay|;
EPSILON <- peer.rootdispersion + peer.dispersion + φ(sys.clock - peer.update);
LAMBDA <- EPSILON + |DELTA| / 2;
end distance procedure;

Si noti che, mentre DELTA può essere negativo in alcuni casi, sia EPSILON che LAMBDA sono sempre positivi.

3.6. Problemi di Controllo degli Accessi

Il design NTP è tale che la modifica accidentale o dolosa dei dati (manomissione, tampering) o la distruzione (interferenza, jamming) presso un server di tempo non dovrebbe in generale risultare in errori di cronometraggio altrove nella sottorete di sincronizzazione. Tuttavia, il successo di questo approccio dipende da server di tempo ridondanti e percorsi di rete diversificati, insieme all'assunzione che la manomissione o l'interferenza non si verifichino contemporaneamente presso molti server di tempo in tutta la sottorete di sincronizzazione. In linea di principio, la vulnerabilità della sottorete può essere ingegnerizzata attraverso la selezione di server di tempo noti per essere affidabili e consentendo solo a quei server di tempo di diventare la fonte di sincronizzazione. Le procedure di autenticazione descritte nell'Appendice C rappresentano un meccanismo per far rispettare questo; tuttavia, gli algoritmi di crittografia possono essere molto intensivi per la CPU e possono degradare seriamente l'accuratezza, a meno che non vengano prese precauzioni come quelle menzionate nella descrizione della procedura di trasmissione.

Sebbene non sia una caratteristica richiesta di NTP stesso, alcune implementazioni possono includere una funzionalità di controllo degli accessi che impedisce l'accesso non autorizzato e controlla quali peer sono autorizzati ad aggiornare l'orologio locale. A questo scopo è utile distinguere tra tre categorie di accesso: quelli che sono preautorizzati come affidabili, preautorizzati come amichevoli e tutti gli altri accessi (non preautorizzati). Presumibilmente, la preautorizzazione viene realizzata tramite voci nel file di configurazione o un qualche tipo di sistema di gestione dei biglietti come Kerberos [STE88]. In questo modello, solo gli accessi affidabili possono risultare nel peer che diventa la fonte di sincronizzazione. Mentre gli accessi amichevoli non possono risultare nel peer che diventa la fonte di sincronizzazione, i messaggi NTP e i timestamp vengono restituiti come specificato.

Non sembra utile mantenere un orologio segreto, come risulterebbe dalla restrizione degli accessi non preautorizzati, a meno che l'intento non sia quello di nascondere l'esistenza del server di tempo stesso. Gli host Internet ben comportati sono tenuti a restituire un messaggio di errore ICMP servizio-non-disponibile se un servizio non è implementato o le risorse non sono disponibili; tuttavia, nel caso di NTP le risorse richieste sono minime, quindi c'è poco bisogno di restringere le richieste destinate solo a leggere l'orologio. Un meccanismo di controllo degli accessi semplice ma efficace consiste quindi nel considerare tutte le associazioni preconfigurate in modalità simmetrica o modalità client (modalità 1, 2 e 3) come affidabili e tutte le altre associazioni, preconfigurate o meno, come amichevoli.

Se è richiesto un modello di fiducia più completo, il design può essere basato su una lista di controllo degli accessi con ogni voce costituita da un indirizzo Internet a 32 bit, una maschera a 32 bit e una modalità a 3 bit. Se l'AND logico dell'indirizzo sorgente (pkt.peeraddr) e della maschera in una voce corrisponde all'indirizzo corrispondente nella voce e la modalità (pkt.mode) corrisponde alla modalità nella voce, l'accesso è consentito; altrimenti viene restituito un messaggio di errore ICMP al richiedente. Attraverso una scelta appropriata della maschera, è possibile restringere le richieste per modalità a indirizzi individuali, un particolare sottorete o indirizzi di rete, o non avere alcuna restrizione. La lista di controllo degli accessi fungerebbe quindi da filtro che controlla quali peer potrebbero creare associazioni.