Sur notre serveur dédié, nous avons parfois besoin de générer des nombres aléatoires avec une forte entropie, par exemple lorsque l’on génère une clé SSH, un certificat SSL/TLS ou une clé pour DNSSEC.
Aujourd’hui, je vous propose donc un article un petit peu plus théorique, qui nous permettra d’améliorer la qualité des données aléatoires et l’entropie générale de notre serveur.
On commence donc par la théorie et on enchaîne sur la partie technique.
L’entropie ou le caractère aléatoire sous Linux
Le chiffrement est basé sur deux facteurs principaux : les nombres premiers et les nombres aléatoires.
Sous Linux, les nombres aléatoires sont générés par le pseudo random number generator (PRNG) qui génère des données aléatoires depuis les interruptions matérielles (clavier, souris, accès disque, accès réseau…) et depuis d’autres sources provenant du système d’exploitation.
Une interruption matérielle (en anglais Interrupt ReQuest ou IRQ) est une interruption déclenchée par un périphérique d’entrée-sortie d’un microprocesseur ou d’un microcontrôleur.
Ce caractère aléatoire ou aléa, que l’on désigne sous le terme entropie, est utilisé principalement pour le chiffrement comme SSL/TLS mais peut aussi avoir plein d’utilisations pratiques (génération de mots de passe, de clés, de chaînes de caractères aléatoires…).
Par exemple, prenons un jeu de dés virtuels : l’entropie permettrait d’améliorer la qualité de l’aléa pour ne pas tomber toujours sur les mêmes nombres.
Il existe deux grands outils aléatoires sous Linux : /dev/random
et /dev/urandom
.
/dev/random
est un fichier spécial qui sert de générateur de nombres aléatoires (ou éventuellement de générateur de nombres pseudo-aléatoires).
Il utilise comme source d’aléa les interruptions matérielles recueillies auprès de pilotes de périphériques et d’autres sources, et les traite à l’aide de fonctions de hachage cryptographiques.
La lecture du fichier est bloquée quand l’activité du système (entropie) n’est pas suffisante, quitte à provoquer un temps de latence.
/dev/urandom
fonctionne de façon analogue en dehors du fait que la lecture n’est pas bloquante : il continue de produire des données “aléatoires” même lorsque la réserve d’entropie se vide ; l’aléa produit est donc moins aléatoire.
En résulte une qualité médiocre des données générées, qui pourraient être des redites des données précédentes.
Apparaissent ainsi d’importants risques de sécurité sur un serveur de production, surtout s’il nécessite des fonctions cryptographiques.
Les dangers d’une entropie trop faible pour les services d’un serveur
Prenons un serveur qui utilise des services chiffrés avec SSL/TLS comme un serveur HTTPS, un serveur de mails entrants/sortants, SSH, SFTP, un client bittorrent…
Si l’un de ces services a besoin de générer de l’aléa alors que toute la réserve d’entropie a été épuisée, il devra faire une pause pour attendre que cette réserve se reconstitue, ce qui peut provoquer un temps de latence excessif dans les applications.
Pire, la plupart des applications récentes définissent leur propre graine aléatoire (random seed) au moment de l’installation ou recourent à /dev/urandom
pour éviter le blocage et risquent de pâtir de la mauvaise qualité des données aléatoires générées.
La graine aléatoire (random seed) est un nombre utilisé pour l’initialisation d’un générateur de nombres pseudo-aléatoires. Toute la suite de nombres produite par le générateur découle de la valeur de la graine de façon déterministe.
Le choix d’une graine aléatoire est une étape cruciale en cryptologie et en sécurité informatique puisqu’elle est souvent générée à partir des composants matériels du système ou bien d’un matériel cryptographique spécifique.
Une solution pour remplir la réserve d’entropie : utiliser le mode utilisateur
Linux obtient de bonnes données aléatoires par les composants matériels mais un serveur Linux ne possède généralement pas de clavier, de souris, de carte son, de carte graphique… ce qui génère bien moins d’entropie.
Les entrées/sorties (Input/Output ou I/O) du disque et du réseau représentent la majorité des sources de génération d’entropie pour ces machines mais ces sources en produisent peu.
Les serveurs possèdent rarement de matériel cryptographique RNG dédié donc ils utilisent le mode utilisateur et les interruptions matérielles pour générer de l’entropie.
Les systèmes d’exploitation actuels partagent la mémoire virtuelle entre le mode noyau (kernel space) et le mode utilisateur (user space ou userland).
Cette séparation permet de fournir une protection de la mémoire qui protège les données et les fonctionnalités des erreurs d’une part (en améliorant la tolérance à la panne) et des comportements malicieux d’autre part (avec la sécurité informatique).
Le mode noyau est lui strictement réservé pour lancer avec certains privilèges le noyau d’un système d’exploitation et la plupart des pilotes des périphériques.
Par contraste, le mode utilisateur est la partie de la mémoire dans laquelle la partie logicielle et quelques pilotes s’exécutent.
HAVEGE : un générateur de nombres aléatoires imprévisibles en mode utilisateur
HAVEGE (HArdware Volatile Entropy Gathering and Expansion) est un générateur de nombres aléatoires imprévisibles en mode utilisateur qui exploite les modifications de l’état interne et volatile des composants comme source d’entropie.
Pendant la phase d’initialisation, le compteur de cycles de l’horloge interne du processeur est utilisé afin de récupérer une partie de cette entropie : en moyenne, des dizaines de milliers de bits imprévisibles peuvent donc être accumulés par chaque appel du système d’exploitation.
Basé sur HAVEGE, haveged permet de générer de l’entropie basée sur les variations des temps d’exécution du code du processeur.
Comme il est quasi impossible pour un morceau de code d’avoir toujours le même temps d’exécution, même sous le même environnement et la même configuration, le temps d’exécution d’un ou de plusieurs processus est une variable suffisamment aléatoire pour créer de l’entropie.
L’implémentation d’haveged remplit la source d’entropie de notre système (/dev/random
) en utilisant les différences du compteur de timestamps (TLC) du processeur après avoir exécuté une boucle de manière répétée.
Installation d’haveged
Pour lister l’entropie disponible sur le serveur, il suffit de lancer :
cat /proc/sys/kernel/random/entropy_avail
Cette commande montre combien d’entropie le serveur a collecté. Si le nombre est faible, c’est-à-dire inférieur à 1000, il faut installer haveged
.
Autrement, les applications nécessitant du chiffrement vont bloquer jusqu’à ce que la réserve d’entropie soit de nouveau suffisante, ce qui entraîne des ralentissements d’exécution.
Sous Debian, il suffit d’installer le paquet haveged
:
apt-get install haveged
Code language: JavaScript (javascript)
Une fois le paquet installé, on édite son fichier de configuration:
nano /etc/default/haveged
Code language: JavaScript (javascript)
et on augmente la taille de la limite d’écriture dans les arguments passés en options :
DAEMON_ARGS="-w 2048"
Code language: JavaScript (javascript)
L’argument -w
spécifie que lorsque /dev/random a moins de 2048 bits d’entropie disponible, les processus qui écrivent vers la réserve d’entropie sont affaiblis. haveged
se réveille alors et produit de l’entropie additionnelle pour que les applications puissent l’utiliser.
On enregistre le fichier et on démarre le service haveged
:
service haveged start
Enfin, on s’assure qu’il démarre bien lors du boot du serveur:
update-rc.d haveged defaults
Code language: CSS (css)
Tester l’entropie avec rng-tools
Mieux que la commande cat
, le paquet nrg-tools
permet de vérifier que notre entropie est correcte. On l’installe donc:
apt-get install rng-tools
Code language: JavaScript (javascript)
et on lance la commande rng-test
qui utilise la méthode FIPS-140 pour vérifier l’entropie:
cat /dev/random | rngtest -c 1000
Résultat:
rngtest 2-unofficial-mt.14
Copyright (c) 2004 by Henrique de Moraes Holschuh
This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
rngtest: starting FIPS tests...
rngtest: bits received from input: 20000032
rngtest: FIPS 140-2 successes: 1000
rngtest: FIPS 140-2 failures: 0
rngtest: FIPS 140-2(2001-10-10) Monobit: 0
rngtest: FIPS 140-2(2001-10-10) Poker: 0
rngtest: FIPS 140-2(2001-10-10) Runs: 0
rngtest: FIPS 140-2(2001-10-10) Long run: 0
rngtest: FIPS 140-2(2001-10-10) Continuous run: 0
rngtest: input channel speed: (min=1.173; avg=15.374; max=26.602)Mibits/s
rngtest: FIPS tests speed: (min=56.430; avg=103.515; max=124.663)Mibits/s
rngtest: Program run time: 1425446 microseconds
Code language: JavaScript (javascript)
La ligne importante à contrôler est la ligne rngtest: FIPS 140-2 failures:
, celle des échecs. Sur 1000 essais, il ne doit pas y avoir un nombre d’échecs supérieur à une fourchette comprise entre 1 et 5.
Conclusion
Comme vous pouvez le constater lors du test FIPS, on pourrait croire qu’en répétant la même boucle, on finirait par générer des données prévisibles mais ce n’est pas le cas. L’entropie est bien respectée.
Voilà ! Engendrer des données aléatoires et imprévisibles est maintenant possible, soit pour générer des clés, soit pour assurer la sécurité de vos services sur le serveur !
Synopsis » Monter un serveur dédié de A à Z
- Serveur dédié : installation d’Apache, PHP, MySQL et Webmin
- Serveur dédié : créer la base de données MySQL et importer WordPress
- Serveur dédié : créer et activer un Virtual Host sous Apache
- Serveur dédié : changer les DNS du nom de domaine et le faire pointer vers le serveur
- Serveur dédié : sécurisation des services avec iptables et fail2ban
- Serveur dédié : sécurisation de la couche TCP/IP
- Serveur dédié : création d’un serveur mail Postfix (sécurisé avec Saslauthd et certificat SSL) et Courier (accès POP et IMAP) utilisant une base MySQL d’utilisateurs/domaines virtuels
- Serveur dédié : sécuriser Apache 2 avec ModSecurity
- Serveur dédié : CHMOD récursif sur des fichiers ou répertoires en ligne de commande
- Serveur dédié : installer APC comme système de cache et configurer Varnish comme reverse-proxy pour Apache pour améliorer les performances
- Serveur dédié : afficher la véritable IP derrière un reverse-proxy comme Varnish
- Serveur dédié : intégrer SSH à WordPress pour mettre à jour le core, les plugins et les thèmes
- Serveur dédié : installer la dernière version d’APC par SVN
- Serveur dédié : analyse des performances du serveur
- Serveur dédié : mettre à jour le noyau Debian de la Kimsufi
- Serveur dédié : sauvegarde automatique des fichiers avec Backup Manager sur le serveur de sauvegarde OVH
- Serveur dédié : configurer la limite mémoire pour PHP et Suhosin
- Bash : supprimer tous les fichiers et sous-répertoires d’un répertoire
- Serveur dédié : impossible de se connecter à un port distant
- Rsync: rapatrier les fichiers du serveur à la maison
- Bash : réparer les tables MySQL en cas de crash
- Serveur dédié : création d’une seedbox avec Transmission
- Serveur dédié : des paquets LAMP à jour sous Debian
- Serveur dédié : mise à jour vers Debian 7 Wheezy
- Serveur dédié : activer X11 forwarding pour SSH
- Serveur dédié : optimiser toutes les images JPG et PNG avec OptiPNG et JpegOptim
- Postfix : résoudre l’erreur “fatal: www-data(33): message file too big”
- Serveur dédié : mise en place de l’IPv6
- WordPress : accorder les bonnes permissions aux fichiers et dossiers avec chown et chmod
- WordPress : héberger les images sur un sous-domaine
- Serveur dédié : ajouter l’authentification SPF, Sender-ID et DKIM à Postfix et Bind9 avec opendkim
- Apache : lorsque le domaine seul (sans WWW) renvoie une erreur 403
- Serveur dédié : sécuriser Apache avec HTTPS (HTTP avec la couche TLS/SSL) en Perfect Forward Secrecy
- Serveur dédié : passer WordPress en HTTPS (TLS/SSL)
- Serveur dédié : configurer Webmin en TLS avec un certificat SSL
- Serveur dédié : configurer Transmission pour accéder au WebUI via TLS-SSL
- Serveur dédié : installer et configurer Varnish 4
- Serveur dédié : passage au mod FastCGI et PHP-FPM avec Apache MPM Worker
- Récupérer un serveur Kimsufi après un plantage de kernel avec le mode rescue OVH
- Serveur dédié : configurer Postfix et Courier pour utiliser TLS-SSL en Perfect Forward Secrecy
- Serveur dédié : retirer Varnish, devenu inutile avec HTTPS
- Serveur dédié : installer la dernière version d’OpenSSL sous Debian
- Serveur dédié : activer l’IP canonique du serveur sous Apache
- Serveur dédié : mise à jour vers PHP 5.6
- MySQL : convertir les tables MyISAM au format InnoDB
- Serveur dédié : optimiser toutes les images GIF avec GIFsicle
- Serveur dédié : migration de MySQL vers MariaDB
- BASH : lister, bloquer et débloquer des adresses IP avec iptables
- Serveur dédié : produire une meilleure réserve d’entropie avec haveged
- Serveur dédié : mettre en place DNSSEC pour sécuriser les DNS du domaine
- Serveur dédié : mise en place du protocole DANE
- 8 règles d’or pour bien déployer DNSSEC et DANE
- Serveur dédié : installer PHP7 FPM avec FastCGI sous Debian
- Serveur dédié : optimiser la couche TCP
- Fail2Ban: protéger Postfix contre les attaques DoS de types AUTH, UNKNOWN et EHLO
- Serveur dédié : mettre à jour Apache pour HTTP/2
- Serveur dédié : ajouter le domaine à la liste HSTS preload
- Serveur dédié : ajouter l’authentification DMARC à Postfix et BIND
- Serveur dédié : à la recherche de l’inode perdue ou comment résoudre le problème “no space left on device”
- Serveur dédié : installer NginX avec support HTTP2 et certificat SSL, PHP, MariaDB sous Debian
Envie d'ajouter des fonctionnalités exceptionnelles à votre site WordPress ou WooCommerce? Je suis là pour vous aider.