Anatomie du paquet NTP#
Pourquoi#
Le chapitre Chrony explique comment un offset est calculé à partir de quatre timestamps, mais jamais à quoi ressemble le paquet qui les transporte réellement sur le réseau. Comprendre la structure de ce paquet, minuscule, 48 octets dans sa forme la plus simple, permet de lire une capture réseau, de comprendre le mode utilisé par ce projet (client-serveur) par opposition aux autres modes que NTP propose, et de découvrir un mécanisme intégré au protocole que ce guide n’avait pas encore montré : le “Kiss-o’-Death”.
Comment : les champs de l’en-tête#
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|LI | VN |Mode | Stratum | Poll | Precision |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Root Delay |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Root Dispersion |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reference ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ Reference Timestamp (64) +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Origin Timestamp (64) [T1] |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Receive Timestamp (64) [T2] |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Transmit Timestamp (64) [T3] |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Extensions (NTS, MAC...), longueur variable |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Le quatrième timestamp (T4, réception) n’apparaît jamais dans le paquet lui-même : il est enregistré localement par le destinataire au moment de la réception, jamais transmis sur le fil.
| Champ | Taille | Rôle |
|---|---|---|
| LI (Leap Indicator) | 2 bits | Annonce une seconde intercalaire imminente (cf. section dédiée ci-dessous) |
| VN (Version) | 3 bits | Version du protocole, 4 aujourd’hui |
| Mode | 3 bits | Rôle de l’émetteur dans l’échange (cf. section Modes) |
| Stratum | 8 bits | Niveau hiérarchique (chapitre Vue d’ensemble), 0 a un sens spécial, voir Kiss-o’-Death |
| Poll | 8 bits | Intervalle d’interrogation, en log₂ secondes |
| Precision | 8 bits | Précision déclarée de l’horloge locale, en log₂ secondes |
| Root Delay / Root Dispersion | 32 bits chacun | Délai et incertitude cumulés jusqu’à la référence stratum 0 |
| Reference ID | 32 bits | Identifiant de la source (chaîne ASCII sur stratum 0/1, ex. PPS0 ; adresse IP du serveur amont sur stratum ≥ 2) |
| Origin/Receive/Transmit Timestamps | 64 bits chacun | T1, T2, T3, cf. section Les quatre timestamps ci-dessous |
Reference ID : le catalogue des sources d’un stratum 1#
Sur un serveur stratum 1, le Reference ID est une chaîne ASCII de 4 caractères qui annonce le type de référence physique qui discipline l’horloge. La RFC 5905 (§ 7.3) en assigne une liste conventionnelle, dont voici les principaux codes :
| Code | Source physique |
|---|---|
GPS | Constellation GPS (États-Unis), reçue par un récepteur satellite |
GAL | Constellation Galileo (Europe) |
PPS | Impulsion par seconde générique, fournie par un équipement externe calibré, quel qu’il soit |
DCF | Émetteur grandes ondes DCF77 (Mainflingen, Allemagne, 77,5 kHz), l’horloge radio historique de l’Europe, encore reçue par des millions de réveils et d’horloges de gare |
MSF | Émetteur grandes ondes MSF (Anthorn, Royaume-Uni, 60 kHz) |
WWVB | Émetteur grandes ondes WWVB (Fort Collins, Colorado, 60 kHz) |
JJY | Émetteurs grandes ondes japonais (Fukushima 40 kHz, Saga 60 kHz) |
TDF | Émetteur d’Allouis (France, 162 kHz), ex-porteuse de France Inter, qui diffuse toujours un code horaire piloté par des horloges atomiques |
CHU / WWV / WWVH | Émetteurs radio HF horaires (Ottawa, Colorado, Hawaï), l’heure “parlée” en ondes courtes |
IRIG | Signal filaire IRIG (Inter-Range Instrumentation Group), distribution d’heure en environnement industriel et militaire |
NIST / ACTS / USNO / PTB | Services d’heure par modem téléphonique des instituts nationaux (NIST et USNO américains, PTB allemande) |
GOES | Satellites météo géostationnaires GOES (États-Unis), service horaire historique |
LORC | Stations de radionavigation LORAN-C (100 kHz), réseau aujourd’hui largement éteint |
Ces codes racontent l’histoire des références de temps : les
émetteurs radio nationaux grandes ondes (DCF, MSF, WWVB, JJY, TDF) et les
services par modem téléphonique (NIST, ACTS) ont précédé le GNSS, qui les
a presque tous supplantés ; PPS ne désigne pas une source en soi mais
l’impulsion électrique de calage qu’une source, quelle qu’elle soit,
fournit à la machine.
Le code exact reste déclaratif : c’est la configuration du serveur
qui le choisit, et rien ne permet à un client de le vérifier. Sur ce
serveur, l’utilisateur a choisi PPS0
(Reference ID : 50505330 (PPS0), soit les codes ASCII de P, P,
S, 0). À partir du stratum 2, le même champ change de nature et
transporte l’adresse IPv4 de la source amont (cf. Erreurs à éviter).
Les quatre timestamps et le calcul d’offset#
L’échange client-serveur repose sur quatre instants, mesurés en alternance par l’horloge du client et par celle du serveur :
Client Serveur
│ │
T1 ●─────────── requête ─────────────► ● T2
│ │ (traitement)
T4 ● ◄────────── réponse ──────────────● T3
│ │- T1 (Origin Timestamp) : départ de la requête, lu sur l’horloge du client ;
- T2 (Receive Timestamp) : arrivée de la requête, lu sur l’horloge du serveur ;
- T3 (Transmit Timestamp) : départ de la réponse, horloge du serveur ;
- T4 : arrivée de la réponse, horloge du client. Ce quatrième instant n’est jamais transmis dans le paquet : chaque machine le note localement à la réception (cf. Erreurs à éviter).
Chaque différence mélange deux inconnues : le décalage réel entre les
deux horloges et le temps de trajet réseau. T2 - T1 contient le
décalage plus le trajet aller ; T3 - T4 contient le décalage
moins le trajet retour. En moyennant les deux, les trajets
s’annulent, à condition d’être égaux :
offset = ((T2 - T1) + (T3 - T4)) / 2
délai = (T4 - T1) - (T3 - T2)Le délai aller-retour, lui, retranche du temps total vu par le client
(T4 - T1) le temps de traitement du serveur (T3 - T2), qui ne
traverse pas le réseau.
Exemple chiffré : un serveur en avance de 100 ms sur le client, 50 ms de trajet dans chaque sens, 20 ms de traitement (en gras, les quatre valeurs réellement mesurées) :
| Instant | Horloge client | Horloge serveur (+100 ms) |
|---|---|---|
| T1 (départ requête) | 0 ms | 100 ms |
| T2 (arrivée serveur) | 50 ms | 150 ms |
| T3 (départ réponse) | 70 ms | 170 ms |
| T4 (retour client) | 120 ms | 220 ms |
offset = ((150 - 0) + (170 - 120)) / 2 = (150 + 50) / 2 = 100 ms (l'avance réelle)
délai = (120 - 0) - (170 - 150) = 120 - 20 = 100 ms (2 × 50 ms de trajet)L’hypothèse implicite, un réseau symétrique dans les deux sens, est la limite fondamentale du protocole : toute asymétrie introduit un biais égal à sa moitié, indétectable depuis les quatre timestamps seuls (chapitre Chrony, Pour aller plus loin). Le déroulé pas à pas de ce calcul est aussi présenté, avec un autre exemple, dans How does NTP work? (sookocheff.com), une des lectures fondatrices de ce chapitre (cf. Sources et remerciements du chapitre Vue d’ensemble).
Les modes NTP#
Le champ Mode (3 bits) indique le rôle joué par le paquet. Ce guide n’en utilise qu’un seul, mais le protocole en définit plusieurs :
| Mode | Usage | Utilisé dans ce guide ? |
|---|---|---|
| Client (3) / Serveur (4) | Le client interroge, le serveur répond : c’est le mode utilisé pour toutes les requêtes vers ce serveur Stratum 1 et vers les sources amont | Oui |
| Symétrique actif/passif (1/2) | Deux serveurs s’interrogent mutuellement en pair-à-pair, chacun pouvant discipliner l’autre, typique entre serveurs de même niveau qui se surveillent mutuellement | Non |
| Broadcast/Multicast (5) | Un serveur diffuse l’heure sans requête individuelle, boucle ouverte, moins précis (aucun calcul de délai réseau possible sans échange bidirectionnel) | Non |
Le mode client-serveur est le bon choix pour ce projet : un serveur public qui répond à des millions de clients anonymes n’a pas vocation à entretenir des associations symétriques avec chacun d’eux, et le broadcast sacrifierait la précision pour un gain de bande passante non pertinent ici.
Kiss-o’-Death : le contrôle de débit intégré au protocole#
Le chapitre nftables montre comment limiter le débit au niveau réseau
(rejet de paquets au-delà d’un seuil). NTP dispose en plus de son propre
mécanisme de rétorsion, au niveau applicatif : quand Stratum = 0, le
champ Reference ID ne contient plus un identifiant de source, mais un
code Kiss ASCII de 4 caractères, d’où le nom “Kiss-o’-Death” (KoD).
| Code | Signification |
|---|---|
RATE | Fréquence d’interrogation trop élevée, l’intervalle de poll doit être augmenté |
DENY / RSTR | Accès refusé par la politique du serveur |
INIT | Le serveur n’est pas encore synchronisé |
C’est un signal coopératif : un client bien élevé (comme chrony) réduit effectivement son taux de requêtes en recevant un
RATE. Un client malveillant peut l’ignorer : c’est pourquoi le rate-limiting réseau du chapitre nftables reste nécessaire en complément : le KoD régule les clients de bonne foi, le pare-feu contient ceux qui ne le sont pas.
Le champ Leap Indicator#
Le chapitre Secondes intercalaires explique le fichier
leap-seconds.list qui informe chrony à l’avance qu’une seconde
intercalaire est programmée. Le champ LI de 2 bits est le mécanisme
par lequel cette information est ensuite répercutée en temps réel à
chaque client, dans chaque paquet, durant les heures qui précèdent
l’événement :
| Valeur LI | Signification |
|---|---|
00 | Pas d’avertissement |
01 | La dernière minute du jour aura 61 secondes |
10 | La dernière minute du jour aura 59 secondes |
11 | Horloge non synchronisée (alarme) |
Erreurs à éviter#
- Confondre le Reference ID d’un stratum 1 et celui d’un stratum
supérieur. Sur ce projet (
Reference ID : 50505330 (PPS0), chapitre Chrony), c’est une chaîne ASCII de 4 caractères. Sur un client interrogeant ce serveur, le Reference ID qu’il verra dans les réponses de ses propres sources amont de stratum ≥ 2 sera au contraire une adresse IPv4, le même champ change de sens selon le stratum de l’émetteur. - Oublier que T4 n’est jamais dans le paquet. Une capture réseau d’un paquet NTP isolé ne contient que 3 des 4 timestamps nécessaires au calcul d’offset ; le quatrième est local à chaque machine, jamais observable depuis l’extérieur.
Vérifier#
# Capturer un échange NTP pour observer les champs réels
tcpdump -i any -n -vv udp port 123 -c 4
# Avec un client NTP capable d'afficher le détail du paquet
ntpdate -d pool.ntp.org 2>&1 | head -30📚 Pour aller plus loin
- RFC 5905 définit la structure complète du paquet NTPv4, tous les champs et leur codage exact.
- Le format des codes Kiss-o’-Death est détaillé au §7.4 de la RFC 5905.
- Le mécanisme d’authentification historique Autokey (RFC 5906), prédécesseur de NTS, est évoqué au chapitre Chrony.