Gimme me more Entropy !

La génération de clef privée sécurisée se sert de l'entropie dont dispose votre serveur.
Très grossièrement (pardon aux puristes), l'entropie représente la qualité de l'aléatoire du votre serveur, la prédictabilité des résultats de certaines commandes. Plus il y a d'entropie, plus vite et plus efficacement vous pouvez générer des clefs (entre autres).

Sur un serveur physique avec un CPU récent, l'entropie est en générale assez élevée. Sur des VM ou si votre CPU est trop basique, elle peut être très faible, et cela augmente de manière assez exponentielle le temps de génération des clefs...
Vous pouvez voir l'entropie disponible sur votre serveur grâce à

cat /proc/sys/kernel/random/entropy_avail

En général, une valeur inférieure à 1000 est assez mauvais signe. Attention sur un Containeur (openvz notamment), cela affiche directement l'entropie de l'hyperviseur, mais openssl sera extrêmement lent même si l'entropie est élevée...

Je vais ici m'inspirer de l'excellent article How to speed up OpenSSL/GnuPG Entropy du tout autant excellent NixCraft. Référez vous aux Sources en fin d'article pour plus de références :-)

Testez votre entropie

Il existe un outil qui permet de tester la qualité et la vitesse de génération de l'entropie de votre serveur.
Il s'agit de rng-tools.

Cet outil est disponible sous debian et centos :

apt-get install rng-tools
systemctl stop rngd.service # Le daemon rngd est installé avec les tools, mais on le coupe sinon ça fausse les tests ;-)

yum install epel-release
yum install rng-tools.x86_64
systemctl stop rngd.service # Le daemon rngd est installé avec les tools, mais on le coupe sinon ça fausse les tests ;-)

Et il va vous permettre de tester le /dev/random de votre PC/serveur/VM/whatever pour faire quelques benchmark afin de vérifier si vous pouvez réellement améliorer la qualité de l'entropie.

Une fois l'outil installé, c'est très simple :

cat /dev/random | rngtest -c 1 # 1, parce que si votre entropie est mauvaise, avec plus vous êtes partis pour des heures...

La commande peut prendre trèès longtemps selon la qualité actuelle de votre entropie, mais notez le résultat, ça servira pour comparer plus tard :-)
Notez particulièrement le "input channel speed" qui est vraiment très lent par défaut (de l'ordre du bit/s).

Quelques exemples pour comparaison

Parce que le nions pas, c'est toujours d'actualité de savoir qui a la plus grosse !
Par ordre de puissance :

Xeon(R) E3-1241 v3 @ 3.50GHz : input channel speed: (min=90.908; avg=90.908; max=90.908)bits/s ---- Program run time: 220002767 microseconds
Core i7-3632QM @ 2.20GHz : input channel speed: (min=33.471; avg=33.471; max=33.471)bits/s ---- Program run time: 597524821 microseconds
Pentium(R) G3450 @ 3.40GHz : input channel speed: (min=25.983; avg=25.983; max=25.983)bits/s ---- Program run time: 769745403 microseconds
Atom(TM) N2800 @ 1.86GHz (à l'intérieur d'un containeur) : input channel speed: (min=37.391; avg=37.391; max=37.391)bits/s ---- Program run time: 534922002 microseconds

Je précise pour la science que ces tests sont fait sur des machines en production, donc avec le CPU fortement sollicité, difficile de déterminer exactement en quoi cela impacte l'entropie..
On voit d'ailleurs que ce n'est pas forcément le CPU le plus costaud qui est le plus efficace !

L'entropie, l'univers et le reste avec RNGD

Voyons maintenant comme on peut améliorer tout ça :-)

rng-tools vient par défaut avec rngd : un daemon dont l'unique rôle est de générer plus d'entropie à travers le matériel présent sur le serveur :-)

Si vous êtes sur un serveur physique, il ne devrait pas y avoir trop de souci. Le service rngd devrait démarrer sans douleur.
Debian :

systemctl start rng-tools

Centos :

systemctl start rngd.service

Vous pouvez ensuite vérifier qu'il tourne bien avec le classique systemctl status nom_du_service

Après ça, ça va dépoter fort !

cat /dev/random | rngtest -c 1

Comparé à tout à l'heure :

Xeon(R) E3-1241 v3 @ 3.50GHz : input channel speed: (min=327.959; avg=327.959; max=327.959)Kibits/s ---- Program run time: 59779 microseconds
Core i7-3632QM @ 2.20GHz : input channel speed: (min=744.473; avg=744.473; max=744.473)Kibits/s ---- Program run time: 26636 microseconds

On voit que le temps s'est incomparablement amélioré pour sortir 1 passe aléatoire. On peut même obtenir des temps bien plus raisonnables sur de très longues passe, 1000 par exemple :

cat /dev/random | rngtest -c 1000

Nous donne :

rngtest: input channel speed: (min=296.094; avg=520.690; max=1218.039)Kibits/s
rngtest: Program run time: 37824064 microseconds

On voit clairement l'amélioration.

Si par contre RNGD démarre pas correctement, les sections suivantes discutent de solutions possibles.

Pas de source d'entropie ?

Vous pouvez obtenir au démarrage les erreurs suivantes :

read error
hwrng: no available rng
Unable to open file: /dev/tpm0
can't open any entropy source
Maybe RNG device modules are not loaded

Ou :

Starting Hardware RNG entropy gatherer daemon: (Hardware RNG device inode not found)
/etc/init.d/rng-tools: Cannot find a hardware RNG device to use.

Dans ces 2 cas, cela signifie que votre serveur ne dispose d'aucun composant matériel permettant de générer de l'entropie. Dit plus simplement, votre CPU est trop pourri...

Vous pouvez vérifier si rngd trouve un générateur d'entropie avec :

# rngd -v # Avec le -v sous Centos, ou sans le -v sous debian
/dev/hwrng: No such device
/dev/tpm0: No such file or directory
Available entropy sources:
DRNG

(ici il a par exemple trouvé DRNG comme source)

Trick avec RNGD (Pour la culture générale)

(va y avoir du gras dans le texte)
Une des solutions peut consister à configurer rngd pour se nourrir de /dev/urandom.

MAIS (je mets un gros MAIS) cette solution n'est pas idéale, voir même dangereuse !
En effet, on se retrouve alors à nourrir /dev/random avec /dev/urandom, ce qui revient à tromper le système en lui faisant croire que ces 2 périphériques donnent des résultats aléatoires différents alors que ce sont les mêmes.

En conséquence, bien que le système pense que l'entropie augmente, elle est en fait de très mauvaise qualité, et dans certains cas elle peut même décroître en réalité.

Si vous comptez vous servir de votre entropie pour de la production (et notamment des clefs de chiffrement) cette technique est à éviter !

Mais comme je sais que vous êtes curieux, je vous la mets quand même pour la culture générale :-)

On va se servir de systemd pour modifier les options de lancement du daemon rngd et lui forcer /dev/urandom comme source d'entropie.

Debian

mkdir -p /etc/systemd/system/rng-tools.service.d
vim /etc/systemd/system/rng-tools.service.d/customexec.conf

Indiquez dans le fichier :

[Service]
ExecStart=
ExecStart=/usr/sbin/rngd -f -r /dev/urandom

Centos

mkdir -p /etc/systemd/system/rngd.d/
vim /etc/systemd/system/rngd.service.d/customexec.conf

Indiquez dans le fichier :

[Service]
ExecStart=
ExecStart=/sbin/rngd -f -r /dev/urandom

Et redémarrez ensuite le service (rng-tools sous Debian, rngd sous Centos).
Je le répète, cette méthode n'est pas à utiliser en production !

On voit que les résultat d'un test d'entropie sont bien plus rapides, mais la qualité ne sera pas au rendez vous :

cat /dev/random | rngtest -c 1000

rngtest: input channel speed: (min=2.918; avg=19.656; max=41.374)Mibits/s
rngtest: Program run time: 1110683 microseconds

Utilisation de Haveged (bon pour la production)

La solution marrante mais moche étant vue, voyons comment s'en tirer sans générateur matériel, de manière réellement utilisable.

Ici, tant qu'à devoir utiliser du logiciel pour générer de l'aléatoire (c'était le concept de /dev/urandom), on va utiliser un algorithme qui est conçu pour et maitrisé :-)
Cet algorithme, c'est HAVEGE, et nous allons l'utiliser via le daemon haveged.

Il suffit donc d'installer le paquet et d'activer le service (désactivé par défaut) :

Debian

aptitude install haveged
systemctl disable rng-tools.service # On désactive rngd pour être sûr de pas avoir de conflits
systemctl start haveged
systemctl enable haveged

Dans le cas de Debian, allez modifier la configuration de /etc/default/haveged pour indiquer : DAEMON_ARGS="-w 1024".

Centos

yum install haveged
systemctl disable rngd.service # On désactive rngd pour être sûr de pas avoir de conflits
systemctl start haveged
systemctl enable haveged

Vous pouvez aussi le laisser désactivé (systemctl disable) et ne le démarrer qu'en cas de besoin.

Avec Haveged, on obtiens également de très bon résultats lors des tests !
Pour 1000 passes :

Pentium(R) G3450 @ 3.40GHz : input channel speed: (min=2.708; avg=19.129; max=34.553)Mibits/s ---- Program run time: 1196145 microseconds
Atom(TM) N2800 @ 1.86GHz (à l'intérieur d'un containeur) : input channel speed: (min=484.190; avg=5526.698; max=3906250.000)Kibits/s ---- Program run time: 4801478 microseconds

Le cas des Containeurs

Si vous utilisez des containeurs (Openvz, et très probablement LXC et Docker), c'est l'entropie de l'hyperviseur qui est directement utilisée.

Il est donc dans ce cas nécessaire d'installer rng ou haveged directement sur l'hyperviseur, de même que la configuration du service. Dans les résultats précédent lancés dans un containeur, le service tournait sur l'hyperviseur, mais le test était effectué depuis l'intérieur.

Sources

Merci à ces différents articles qui m'ont été bien utiles !


Victor Avatar Victor est le rédacteur principal du blog.
Comments

Si vous avez des questions, si quelque chose n'est pas clair, n'hésitez pas à commenter !

Il n'y a aucun commentaire pour l'instant. / There are no comments yet.

Ajouter un commentaire / Add a Comment

Vous pouvez utiliser la syntaxe Markdown pour formatter votre commentaire.

You can use the Markdown syntax to format your comment.

Flux Atom pour commentaire / Comment Atom Feed

Published

Category

Système

Tags

Restez en contact