lalahop

Installer un serveur NTP sur OpenWRT

Table des matières

Pourquoi ?

Vous avez peut-être lu mon billet sur comment utiliser un client NTP sous OpenWRT et vous vous demandez peut-être pourquoi je décide maintenant d'utiliser un serveur.

Tout simplement car je me suis aperçu que j'avais fait une erreur lors de mon choix d'utiliser seulement un client NTP.

En effet, comment vais-je synchroniser les autres machines de mon réseau ? Comme avant, en utilisant un serveur externe ? Avouez que cela fait beaucoup de requêtes, ce qui encombre inutilement ma bande passante comme la bande passante du serveur externe. De plus, si la connexion au net tombe, un serveur local permettra de conserver le même temps (qui perdra en précision, certes) sur toutes les machines du LAN.

De plus, un serveur NTP permet une plus grande précision (certains se demanderont si on a besoin d'une telle précision ... à chacun de juger). À titre d'exemple : selon la documentation officielle, ntpclient utilise le premier serveur qu'il peut joindre parmi ceux que vous lui avez spécifiés. NTPd utilise des algorithmes plus complexes pour déterminer le meilleur serveur de temps de la liste.

Il doit surement y avoir d'autres arguments en faveur d'un serveur NTP mais je pense que je vous ai donné les principaux

Quel serveur choisir ?

root@OpenWrt:~# opkg list | grep -i NTP
chrony - 1.23-3 - A NTP implementation that has been specifically written to work
 connection to the network where your NTP servers are.
[...]
ntpd - 4.2.6-4 - The ISC ntp suite is a collection of tools used to synchronize
 the system clock with remote NTP time servers and run/montior
 local NTP servers.
 This package contains the ntpd server.
[...]
openntpd - 3.9p1-3 - A free and easy to use NTP (Network Time Protocol) implementation.

OpenWRT donne le choix entre trois implémentations du protocole NTP :

  • ntpd de ntp.org, le démon de référence maintenu par l'ISC.
  • openntpd, un démon maintenu par le projet OpenBSD.
  • chronyd, un démon NTP à préférer en cas de connexion instable au réseau.

Ma connexion est relativement stable donc chrony n'est pas fait pour moi. Le choix entre openntpd ou ntpd dépend de vos préférences ... Openntpd est sous licence BSD, ntpd est sous licence ISC. Openntpd est une implémentation allégée avec une configuration plus simple (je n'ai pas dit "simpliste" !) du protocole NTP mais le fait qu'il soit développé par l’équipe du projet OpenBSD est un gage de sécurité supplémentaire (openntpd tourne sous un compte sans droits par exemple). ntpd propose une configuration plus touffue (je n'ai pas dis "plus efficace"), un mécanisme d'authentification ainsi que des outils permettant de surveiller le fonctionnement du démon, ce que ne propose pas openntpd. Opennptd propose un système de poids pour choisir la priorité des serveurs NTP à interroger plutôt qu'une simple option "prefer" comme ntpd ... Bref, comme vous le voyez, la décision vous revient, dépend de vos besoins et est très personnelle.

Personnellement, j'ai choisi ntpd, le démon historique pour 2 raisons :

  • Sous OpenWRT, openntpd réclame le support de l'ipv6 (sinon un message "fatal: client_query socket: Address family not supported by protocol" s'affichera lors du lancement. Il faut donc installer le package kmod-ipv6. Je ne souhaite pas avoir le support ipv6 sur mon routeur pour l'instant (tant que mon FAI ne me proposera pas du full ipv6 en fait) et donc m’encombrer d'un package inutile. Source : can't start the NTP daemon (openntpd) sur forum.openwrt.org
  • Openntpd ne permet pas de déplacer le fichier servant à stocker la dérive de l'horloge. Celui-ci se trouve dans /var/db qui est un répertoire tmpfs donc effacé au redémarrage du routeur. Donc le serveur doit recalculer la dérive à chaque redémarrage. Même si ce n'est pas une opération lourde, c'est dommage.

Dans la suite de ce guide, je m’intéresserai donc uniquement à ntpd de ntp.org.

Installation de ntpd

Vous avez l'habitude :

opkg update && opkg install ntpd

Configuration de ntpd

Modification du fichier de configuration

La configuration se fait dans le fichier /etc/ntp.conf (attention, pas de "d" à "ntp" !). Voici le fichier que je vous propose :

## Les serveurs externes qui seront utilisés pour se synchroniser (strate 1 et 1)
server ntp-p1.obspm.fr iburst prefer
server canon.inria.fr iburst
 
## Contrôle des accès
# Par défaut, on ne répond à rien ...
restrict default ignore

# ... exception faite des serveurs externes sur lesquels on va se synchroniser ... 
# (rien ne circule sauf la correction du temps : dans l'ordre, on n'autorise 
# pas la création de hooks pour des journaux à distance, on ne peut pas consulter 
# ou modifier la configuration du serveur, les serveurs ne peuvent pas tenter 
# d'établir une connexion en tant que peer)
restrict ntp-p1.obspm.fr mask 255.255.255.255 nomodify notrap nopeer noquery
restrict canon.inria.fr mask 255.255.255.255 nomodify notrap nopeer noquery

# ... et des stations du réseau local (on peut demander le temps et consulter 
# l'état du serveur, les autres actions sont refusées)
restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap nopeer
 
# ... et en local (on peut tout faire)
restrict 127.0.0.1
## Fin du contrôle des accès
 
# On stocke le décalage de l'horloge système. Cela permet de maintenir, un peu, 
# l'heure en cas de coupures du net. Ne pas placer ce fichier dans un répertoire 
# temporaire : cela évite aussi à ntpd d'avoir à refaire les calculs permettant
# de déterminer la dérive de l'horloge après chaque redémarrage.
driftfile  /etc/ntp.drift

Malgré les commentaires, je souhaite ajouter quelques détails :

  • Pour trouver des serveurs NTP, vous pouvez faire une recherche Google et/ou consulter le site du Comité Réseau des Universités. Veuillez à respecter les conditions d'utilisation (ce n'est pas compliqué à envoyer, un mail). Essayez de choisir des serveurs qui ne sont pas sur le même réseau/FAI afin d'accroître la redondance en cas de problème sur un réseau. Ce point est relativement compliqué vu que beaucoup de serveur sont fournis par l'enseignement supérieur et donc sont sur le réseau RENATER. Ce point n'est pas non plus le point capital : même si tout un réseau venait à tomber (ce qui est déjà rare), votre horloge ne sera pas instantanément déréglée E de plusieurs minutes. Par contre, veuillez à choisir des serveurs qui ne sont pas dépendant l'un de l'autre. Exemple : vous choisissiez d'utiliser S1 et S2, deux serveurs pris au hasard et vous vous rendez compte qu'en fait S2 se synchronise sur S1 ... Pour vérifier cela, utilisez la commande "ntpq -np <ip_du_serveur>" sur chaque serveur que vous souhaitez utiliser.
  • Comme vous pouvez le constater, j'utilise des serveurs de strate 1. On pourra discuter sur les usages qu'un particulier peut faire de ces serveurs et de la précision associée. On pourra également s'interroger sur qui a réellement besoin d'une horloge en strate 2 et de sa grande précision (pourvu que la source soit fiable) : une PME, une institution bancaire, l'armée ?! Bref, je m'arrête là. Bien qu'on recommande habituellement l'usage de serveurs de strate 2 voire 3 pour un particulier, je signale que je ne suis pas le seul à utiliser un serveur de strate 1 : voir à ce sujet l'article "Installation pas à pas de Debian 6.0 (Squezze)" dans GNU/Linux Magazine/France n°139 de juin 2011.
  • L'option iburst permet de répéter les tentatives quand un serveur est inaccessible.
  • L'option prefer permet de marquer un et un seul serveur comme étant ... notre serveur de temps de référence préféré.

ÉDIT 25/08/2011 à 2h15 :
Attention :
De nombreux guides (y compris celui-ci avant cette correction) suggèrent d'utiliser l'horloge locale en insérant les lignes suivantes dans le fichier de configuration :

server 127.127.1.0
fudge 127.127.1.0 stratum 10

Cela permet, en théorie, d'utiliser l'horloge locale afin que le serveur continue à fonctionner dans le cas où les serveurs externes deviendraient inaccessibles. Cela permet également de pouvoir synchroniser les clients alors que le serveur n'est pas encore totalement synchronisé avec les serveurs externes. Et, en effet, cela fonctionne.

Mais sur OpenWRT, lors de chaque reboot, l'horloge revient à l'heure de compilation du noyau. Probablement car il n'y a pas de circuit temporel sur le WRT54GL. Donc, le fait d'utiliser l'horloge locale comme référence fait que ntpd va mettre doucement à jour l'heure au lieu de la mettre brutalement à jour au démarrage du système puis de la synchroniser régulièrement. Et comme le décalage est important, la synchronisation initiale va prendre beaucoup de temps. Trop de temps. Donc, je ne conseille pas cette option sous OpenWRT.
Fin de l'édit

A noter : Par défaut, ntpd envoie ses journaux à syslog. Ils sont donc accessibles via la commande logread. Si vous voulez les enregistrer dans un fichier différent, il est possible d'utiliser l'option "logfile /path/fichier" dans le fichier de configuration. Il est également possible d'utiliser l'option "logconfig" pour régler les informations qui seront logguées (via syslog ou via le fichier). "logconfig +all" permet de tout logguer. Je ne conseille néanmoins pas cette option sur le long terme vu la masse d'information qui est envoyée mais elle peut servir lors d'une phase de débogage. Referez-vous au man pour voir les autres valeurs que peut prendre cette option.

Il n'y a rien d'autre à configurer : un script d'init et un script pour le démon hotplugd ont déjà été fourni par OpenWRT.

On pensera tout de même à configurer convenablement le pare-feu du routeur. Mais là, c'est une autre histoire 🙂 .

Faire en sorte que ntpd n'écoute pas sur toutes les interfaces réseau

Pour cela, ntpd possède un paramètre, "-I", qui permet de préciser les interfaces sur lesquelles le démon écoutera. Bizarrement, il faut indiquer également l'interface de sortie (= l'interface par laquelle les paquets à destination des serveurs NTP externes passeront). De ce fait, ntpd doit, au minimum, écouter sur l'interface externe et sur l'interface LAN. Il le fait par défaut donc pas besoin de lui indiquer. Si vous avez plusieurs VLAN et que vous ne voulez pas proposer de serveur NTP sur l'un d'eux, il est préférable, à mon avis, de ne pas autoriser le plan d'adressage de ce VLAN dans le fichier de configuration de ntpd voir de bloquer le trafic NTP avec iptables. Si malgré tout vous voulez faire en sorte que ntpd écoute uniquement sur les interfaces que vous spécifiez, voici comment procéder.

Il suffit de modifier le fichier /etc/init.d/ntpd. Dans la fonction start, la ligne :

/usr/sbin/ntpd -g -p $PIDFILE

devient :

/usr/sbin/ntpd -g -p $PIDFILE -I <1ere_interface> -I <2eme interface>

Puis, relancez le démon :

/etc/init.d/ntpd restart

"ignore" versus serveur de strate >= 2

En effet, si vous utilisez un serveur dont la strate d'appartenance est supérieure à 1 combiné avec l'option de configuration "restrict default ignore", vous obtiendrez une sortie ressemblant à celle ci-dessous avec l'outil ntpq -p :

91.121.20.142   .INIT.          16 u    -   64    0    0.000    0.000   0.000

Votre serveur tente de savoir sur quel serveur se synchronise le serveur de strate > 1 que vous avez défini dans le fichier de configuration et il n'y parvient pas. Ce qui est normal puisque le serveur de référence du serveur de strate > 1 que vous utilisez n'a pas été autorisé dans le fichier de configuration. Le serveur défini est donc exclu du processus de sélection d'un serveur de référence. Cela n'a donc rien à voir avec les pool qui utilisent des serveurs aléatoires et ne permettent donc pas à ntpd de pouvoir réaliser l'association avec eux comme on le lit sur certains forums.

Deux méthodes s'offrent à vous pour résoudre ce problème :

  1. Ne pas utiliser l'option "restrict default ignore" dès le début afin de connaître les adresses des serveurs sur lesquels se synchronisent les serveurs que vous utilisez. Ainsi, vous n'avez plus qu'à les autoriser explicitement dans votre ntp.conf et à appliquer l'option "restrict default ignore" par la suite.
  2. La méthode n°1 trouvera ses limite dans le cas d'un pool de serveurs (ex. : fr.pool.ntp.org) car le serveur qui vous sert de référence change souvent (round-robin DNS (= fr.pool.ntp.org ne pointe pas toujours sur le même serveur de temps). Il vous faudrait donc pas mal de temps pour faire la liste complète de tous les serveurs qui servent de référence aux serveurs du pool. Dans ce cas là, au lieu d'utiliser l'option "restrict default ignore", vous devez utiliser l'option "restrict default notrap noquery nopeer". Vous pouvez supprimer les règles restrict que nous avons créées pour chaque serveur. Cela signifie aussi que toute machine arrivant à contacter votre routeur pourra se synchroniser sur celui-ci. Attention donc à bien configurer iptables sur l'interface eth0.1 si vous voulez éviter que votre bande passante ne soit pompée par des bots.

Test

D'abord, voyons les commandes que nous allons utiliser :

  • ntpq se trouve dans le package ntp (Debian) ou ntp-utils (OpenWRT). Vous pouvez utiliser cette commande depuis votre routeur.
  • ntpdate se trouve dans le package ntpdate (Debian).

Pour tester votre serveur, il vous suffit d'utiliser la commande ntpq -pn (l'adresse est facultative si vous lancez la commande depuis votre routeur). Vous devez obtenir une sortie qui ressemble à celle-ci :

     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 145.238.203.14  .TS-2.           1 u   25   64    1   41.906  -35.002   0.113
 192.93.2.20     .GPSi.           1 u   24   64    1   42.545  -35.312   0.222
*127.127.1.0     .LOCL.          10 l   33   64    1    0.000    0.000   0.031

En essayant quelques dizaines de minutes plus tard (ça peut aller jusqu'à 30 minutes voire 1 heure), vous obtiendrez quelque chose comme :

     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*145.238.203.14  .TS-2.           1 u   20   64    7   41.446  -38.169   3.057
+192.93.2.20     .GPSi.           1 u   22   64    7   42.545  -35.312   1.275
 127.127.1.0     .LOCL.          10 l   93   64    6    0.000    0.000   0.031

Vous constatez que le serveur ntp-p1.obspm.fr a été choisi comme serveur de référence et que le serveur canon.inria.fr est candidat en cas de problème. L'horloge locale a, quand a elle, été rejetée par l'algorithme de sélection. La valeur du champ pool doit augmenter progressivement jusqu'à atteindre 1024. La valeur du champ reach doit augmenter progressivement (1, 3, 7, 17, 37, 77, 177) jusqu'à atteindre 377. Cela indique que les 8 dernières tentatives de connexion à ce serveur ont réussi. En effet, chaque tentative réussie est marquée avec le chiffre 1 et chaque échec est marqué avec le chiffre 0. Ainsi, 2 réussites sur 2 essais donnent 11 en binaire et donc 3 en octal. 8 réussites sur 8 essais donnent 11111111 en binaire et donc 377 en octal.

D'autres commandes de ntpq permettent d'obtenir l'état des serveurs de référence de votre serveur (ex. : ntpq -c 'associations' 192.168.1.1) mais je ne vous les expliquerai pas dans ce billet. Reportez-vous au man ntpq pour obtenir plus d'informations.

Si tout est en ordre, vous êtes en mesure de synchroniser votre ordinateur avec votre routeur. Pour tester cela, utilisez la commande ntpdate . Vous devez obtenir une sortie ressemblant à celle-ci :

24 Aug 02:03:04 ntpdate[2448]: adjust time server 192.168.1.1 offset 0.002604 sec

Configuration des clients

Pour synchroniser vos clients en temps réel, je vous recommande d'utiliser ntpd/openntpd/chronyc plutôt que de créer une cron qui lancera ntpdate régulièrement pour la simple et bonne raison que ntpd permet un ajustement plus doux de l'horloge et qu'il ne consomme que très peu de ressources.

La configuration d'un client avec ntpd se fait comme nous l'avons vu : on définit le serveur sur lequel on se synchronise (le routeur), on ne répond à rien sauf aux requêtes locales et on laisse sortir les requêtes vers le routeur. En somme, on utilise un fichier ntp.conf comme celui-ci :

server 192.168.1.1 iburst prefer
 
server 127.127.1.0
fudge 127.127.1.0 stratum 10

restrict default ignore
restrict 192.168.1.1 mask 255.255.255.255 nomodify notrap nopeer noquery
restrict 127.0.0.1
 
driftfile  /etc/ntp.drift

Et on ajuste les règles du pare-feu en conséquence.

Pour aller plus loin avec NTPD

Je vais vous proposer quelques idées pour peaufiner votre installation et vous faire cogiter encore un peu 😉 .

Rendre son serveur public ?

Si vous répondez aux exigences demandées, vous pouvez envisager d'ouvrir votre serveur au public. Dans ce cas-là, pensez à modifier le fichier de configuration car le "restrict default ignore", ça va pas l'faire 😉 .

Vous pouvez également mettre en place de la QoS afin que votre bande passante ne soit pas entièrement consommée par des requêtes NTP.

Dans le fichier de configuration de ntpd, vous pouvez utiliser la directive "discard", qui permet d'appliquer des limites de nombre de paquets pour éviter les abus des clients. Utilisez ensuite la directive "limited" pour appliquer ces restrictions. Exemple :

discard average 3 minimum 2
restrict default notrap noquery nopeer limited

Ici, nous spécifions un espacement minimum entre les requêtes de 2 secondes et un espacement minimum moyen entre les requêtes de 8 secondes.

Attention : average est donné en log2. Ainsi, si vous voulez 8 secondes d'espacement minimum moyen entre deux paquets, vous indiquerez la valeur 3 (car log2(8) = 3). Utilisez ce convertisseur. La valeur de l'option "minimum" est donnée en secondes.

Enfin, vous pouvez activer l'envoi d'un paquet KoD (Kiss-of-Death) : il permet d'informer le client qu'il a dépassé les limites mises en place avec discard. Il doit donc cesser d'envoyer autant de paquets sinon il ne sera plus en mesure de récupérer le temps sur notre serveur. Activer cette option n'est pas nécessaire car, par défaut, les paquets qui dépassent la limite sont ignorés de toute façon. Mais informer le client permet d'avertir les clients un peu trop "speed".

Voir la documentation officielle pour plus d'informations sur discard/limited/kod.

Après, rien ne vous empêche d'ouvrir votre serveur pour vos proches/amis ou de le rendre totalement public même si vous ne pouvez pas rejoindre le pool ntp.org.

Me concernant, ma connexion ne répond pas aux exigences (ip dynamique, bande passante qui sera limite en pointe). Mon serveur restera donc privé.

Sécuriser la liaison entre votre serveur et vos clients

Il est possible de sécuriser ces échanges à l'aide de la cryptographie à clé publique ou de la cryptographie symétrique. OpenWRT propose ntpd avec le support d'OpenSSL dans le package ntpd-ssl.

Comme je ne souhaite pas cela en place sur mon LAN, je vous laisse vous débrouiller.

Devenir votre propre référence

Non, je ne suis pas fou. Si tout le monde n'a pas une horloge atomique chez soi ( 🙂 ), certains peuvent avoir un module GPS qui se branche sur un port série ou sur un port USB. Ce module peut être utilisé comme source de temps puisque les satellites GPS contiennent des horloges atomiques qui leur permettent de rendre leur service. Le temps acquis par le module peut être diffusé par ntpd sur l'ensemble de votre réseau.

Comme je n'ai pas ce matériel sous la main, je vous laisse, là encore, vous débrouiller 8) .

Références documentaires