<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>~/</title><link href="https://blog.blaisot.org/" rel="alternate"></link><link href="https://blog.blaisot.org/feeds/all.atom.xml" rel="self"></link><id>https://blog.blaisot.org/</id><updated>2018-03-19T17:00:00+01:00</updated><entry><title>Si on se faisait un petit certificat wildcard ? - Partie 2</title><link href="https://blog.blaisot.org/letsencrypt-wildcard-part2.html" rel="alternate"></link><published>2018-03-19T17:00:00+01:00</published><updated>2018-03-19T17:00:00+01:00</updated><author><name>sblaisot</name></author><id>tag:blog.blaisot.org,2018-03-19:letsencrypt-wildcard-part2.html</id><summary type="html">

&lt;p&gt;Dans &lt;a href="letsencrypt-wildcard-part1.html"&gt;l’article précédent&lt;/a&gt;, je vous ai expliqué comment installer la bonne version de certbot pour générer des certificats wildcard letsencrypt et je vous ai montré comment en générer un avec une édition manuelle de la zone DNS.&lt;/p&gt;
&lt;p&gt;Dans ce second article de cette série sur la génération de certificats wildcard letsencrypt, je vais vous montrer comment générer automatiquement un certificat wildcard.&lt;/p&gt;
&lt;p&gt;Nous allons commencer par un domaine dont le DNS est géré sur un fournisseur DNS pour lequel il exist un plugin pour certbot. Nous utiliserons AWS route53 dans cet exemple&lt;/p&gt;
&lt;p&gt;Ensuite, nous verrons comment utiliser des scripts maison pour faire l’ajout de l’entrée DNS nécessaire au challenge ACME DNS-01 (le protocole de validation pour l’émission du certificat wildcard). Nous utiliserons cette technique pour générer des certificats lorsque la zone DNS est hébergée sur un bind local ou lorsqu’elle est hébergée sur les DNS de gandi (LiveDNS) ou d'OVH.&lt;/p&gt;
&lt;div class="toc"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#generation-de-certificat-wildcard-avec-dns-route53"&gt;Génération de certificat wildcard avec DNS route53&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#generation-de-certificat-wildcard-avec-scripts-maison-dedition-de-zone"&gt;Génération de certificat wildcard avec scripts maison d’édition de zone&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#fonctionnement"&gt;Fonctionnement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#un-script-pour-tester"&gt;Un script pour tester&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#generation-de-certificat-wildcard-avec-dns-bind-local"&gt;Génération de certificat wildcard avec DNS bind local&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#generation-de-certificat-wildcard-avec-dns-gandi-livedns"&gt;Génération de certificat wildcard avec DNS Gandi (LiveDNS)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#generation-de-certificat-wildcard-avec-dns-ovh"&gt;Génération de certificat wildcard avec DNS OVH&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#points-complementaires"&gt;Points complémentaires&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#emplacement-des-scripts-et-renouvelement"&gt;Emplacement des scripts et renouvèlement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#delai-de-creation-de-lentree-dns"&gt;Délai de création de l’entrée DNS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#et-la-securite-dans-tout-ca"&gt;Et la sécurité dans tout ça ?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#conclusion"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;


&lt;h1 id="generation-de-certificat-wildcard-avec-dns-route53"&gt;Génération de certificat wildcard avec DNS route53&lt;/h1&gt;
&lt;p&gt;Pour pouvoir créer les entrées DNS nécessaires à la validation du domaine, il vous faudra une clé d’accès et une clé secrète pour l’API AWS. Vous devez donc commencer par créer un utilisateur dans la &lt;a href="https://console.aws.amazon.com/iam/home#/users"&gt;console IAM&lt;/a&gt; de la façon suivante :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Choisissez “Ajouter un utilisateur”&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Appelez-le “letsencrypt_validation” par exemple et choisissez un accès par programmation (pour obtenir une clé d’API) et cliquez sur “Suivant”
&lt;img alt="img1" src="/static/img/letsencrypt-wildcard/AWS_IAM_01.jpg" title="" /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choisissez d’attacher directement les stratégies existantes et cliquez sur “Créer une stratégie” pour créer les droits de votre nouvel utilisateur
&lt;img alt="img2" src="/static/img/letsencrypt-wildcard/AWS_IAM_02.jpg" title="" /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Créez une nouvelle stratégie pour le service Route53 qui autorise les actions “GetChange”, “ListHostedZones” et “ChangeRessourceRecordSets” sur tous les objets (vous pouvez sinon restreindre l’action “ChangeRessourceRecordSets” sur les seuls domaines pour lesquels vous souhaitez pouvoir effectuer une validation DNS-01)
&lt;img alt="img3" src="/static/img/letsencrypt-wildcard/AWS_IAM_02_1.jpg" title="" /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Nommez votre stratégie (par exemple &lt;em&gt;letsencrypt_validation&lt;/em&gt;) et validez
&lt;img alt="img4" src="/static/img/letsencrypt-wildcard/AWS_IAM_02_2.jpg" title="" /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Revenez à votre utilisateur en cours de création, cliquez sur “Actualiser” pour recharger la liste des stratégies puis recherchez celle que vous venez de créer et cochez la case en début de ligne pour l’associer à votre utilisateur, puis cliquez sur “Suivant”
&lt;img alt="img5" src="/static/img/letsencrypt-wildcard/AWS_IAM_02_3.jpg" title="" /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Vérifiez le résumé et cliquez sur “Créer un utilisateur” pour procéder à la création
&lt;img alt="img6" src="/static/img/letsencrypt-wildcard/AWS_IAM_03.jpg" title="" /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dans le résumé de création de l’utilisateur, notez l’ID de clé d’accès ainsi que la clé d’accès secrète qui vous serviront à vous authentifier auprès de l’API route53
&lt;img alt="img7" src="/static/img/letsencrypt-wildcard/AWS_IAM_04.jpg" title="" /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Le plugin route53 de certbot utilise ces identifiants. Nous allons donc installer le paquet &lt;code&gt;awscli&lt;/code&gt; et configurer les identifiants :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ apt-get install awscli
$ aws configure
AWS Access Key ID &lt;span class="o"&gt;[&lt;/span&gt;None&lt;span class="o"&gt;]&lt;/span&gt;: AKIAXXXXXXXXXXXXXXXX
AWS Secret Access Key &lt;span class="o"&gt;[&lt;/span&gt;None&lt;span class="o"&gt;]&lt;/span&gt;: 74Bo!xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Default region name &lt;span class="o"&gt;[&lt;/span&gt;None&lt;span class="o"&gt;]&lt;/span&gt;: eu-central-1
Default output format &lt;span class="o"&gt;[&lt;/span&gt;None&lt;span class="o"&gt;]&lt;/span&gt;:
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Nous allons ensuite installer le plugin route53 de certbot :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ /opt/eff.org/certbot/venv/bin/pip install certbot-route53
Collecting certbot-route53
  Downloading certbot-route53-0.2.0.tar.gz
&lt;span class="o"&gt;[&lt;/span&gt;...&lt;span class="o"&gt;]&lt;/span&gt;
Successfully built certbot-route53
Installing collected packages: jmespath, python-dateutil, docutils, botocore, futures, s3transfer, boto3, certbot-dns-route53, certbot-route53
Successfully installed boto3-1.6.11 botocore-1.9.11 certbot-dns-route53-0.22.0 certbot-route53-0.2.0 docutils-0.14 futures-3.2.0 jmespath-0.9.3 python-dateutil-2.6.1 s3transfer-0.1.13
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Et nous avons désormais tout ce qu’il nous faut pour générer un certificat wildcard letsencrypt avec un domaine géré sur route53. Nous utiliserons les options suivantes de certbot :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--server https://acme-v02.api.letsencrypt.org/directory&lt;/code&gt;  On utilise l’API ACME v2&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--dns-route53&lt;/code&gt; L’entrée DNS pour le challenge sera créée via l’api route53&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-d '*.domain.tld'&lt;/code&gt; le sujet du certificat qu’on souhaite émettre&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; /opt/eff.org/certbot/venv/bin
$ ./certbot certonly &lt;span class="se"&gt;\&lt;/span&gt;
    --server https://acme-staging-v02.api.letsencrypt.org/directory &lt;span class="se"&gt;\&lt;/span&gt;
    --dns-route53 &lt;span class="se"&gt;\&lt;/span&gt;
    -d &lt;span class="s1"&gt;&amp;#39;*.domain.tld&amp;#39;&lt;/span&gt;
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Found credentials in shared credentials file: ~/.aws/credentials
Plugins selected: Authenticator dns-route53, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge &lt;span class="k"&gt;for&lt;/span&gt; domain.tld
Starting new HTTPS connection &lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;: route53.amazonaws.com
Waiting &lt;span class="m"&gt;10&lt;/span&gt; seconds &lt;span class="k"&gt;for&lt;/span&gt; DNS changes to propagate
Waiting &lt;span class="k"&gt;for&lt;/span&gt; verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/domain.tld/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/domain.tld/privkey.pem
   Your cert will expire on 2018-06-15. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   &lt;span class="s2"&gt;&amp;quot;certbot renew&amp;quot;&lt;/span&gt;
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;s Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Et voilà ! nous avons généré automatiquement notre certificat wildcard letsencrypt pour un domaine géré sur route53. Et comme la validation s’est faite automatiquement, sans intervention manuelle, la renouvèlement se passera de la même façon.&lt;/p&gt;
&lt;h1 id="generation-de-certificat-wildcard-avec-scripts-maison-dedition-de-zone"&gt;Génération de certificat wildcard avec scripts maison d’édition de zone&lt;/h1&gt;
&lt;h2 id="fonctionnement"&gt;Fonctionnement&lt;/h2&gt;
&lt;p&gt;Lors d’une génération de certificat avec validation manuelle, &lt;code&gt;certbot&lt;/code&gt; dispose des options &lt;code&gt;--manual-auth-hook&lt;/code&gt; et &lt;code&gt;--manual-cleanup-hook&lt;/code&gt; qui permettent de définir des scripts qui doivent être appelés pour créer l’entrée dns avant la validation puis pour la supprimer après. Voir à ce sujet la &lt;a href="https://certbot.eff.org/docs/using.html#pre-and-post-validation-hooks"&gt;documentation officielle&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ces scripts sont appelés avec les variables d’environnements suivantes définies (pour une validation DNS-01) :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CERTBOT_DOMAIN&lt;/code&gt; : le domaine à valider&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CERTBOT_VALIDATION&lt;/code&gt; : le contenu de l’entrée TXT à créer&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Le script de nettoyage post-validation reçoit également la variable d’environnement &lt;code&gt;CERBOT_AUTH_OUTPUT&lt;/code&gt; qui contient la sortie standard du script de validation. Ceci peut servir par exemple à passer entre les 2 scripts l’ID de l’enregistrement créé.&lt;/p&gt;
&lt;p&gt;Je vous ai mis &lt;a href="https://github.com/sblaisot/certbot-dns-01-authenticators"&gt;dans github&lt;/a&gt; tous les scripts utilisés ci-dessous. Ces scripts sont des exemples pour vous aider à développer les vôtres. Commencez par cloner ces scripts dans &lt;code&gt;/opt/le-scripts&lt;/code&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;    $ git clone https://github.com/sblaisot/certbot-dns-01-authenticators.git /opt/le-scripts
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;4 ensembles de scripts sont disponibles, le premier pour tester le fonctionnement de certbot avec des scripts de validation personnels, le second si vous avez votre serveur DNS bind sur la même machine que celle avec laquelle pour générez les certificats et les deux derniers pour générer des certificats wildcard letsencrypt lorsque vos zones DNS sont gérées sur le service LiveDNS de Gandi ou chez OVH.&lt;/p&gt;
&lt;p&gt;Chaque ensemble est composé de 2 scripts : un script &lt;code&gt;auth&lt;/code&gt; qui permet de créer l’entrée DNS pour la validation et un script &lt;code&gt;cleanup&lt;/code&gt; qui permet de la retirer une fois la validation effectuée.&lt;/p&gt;
&lt;h2 id="un-script-pour-tester"&gt;Un script pour tester&lt;/h2&gt;
&lt;p&gt;Les scripts du répertoire &lt;code&gt;test&lt;/code&gt; se contentent d’afficher le contenu des variables d’environnements passées par certbot, pour en étudier le fonctionnement. De ce fait, ils ne créent ni ne suppriment aucune entrée DNS et la génération de certificat échoue forcément.&lt;/p&gt;
&lt;p&gt;Néanmoins, ils nous permettent de voir comment cela fonctionne. Appelons &lt;code&gt;certbot&lt;/code&gt; en lui demandant d’utiliser ces scripts :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; /opt/eff.org/certbot/venv/bin
$ ./certbot certonly &lt;span class="se"&gt;\&lt;/span&gt;
    --server https://acme-staging-v02.api.letsencrypt.org/directory &lt;span class="se"&gt;\&lt;/span&gt;
    --manual-public-ip-logging-ok &lt;span class="se"&gt;\&lt;/span&gt;
    --manual &lt;span class="se"&gt;\&lt;/span&gt;
    --manual-auth-hook /opt/le-scripts/test/auth.sh &lt;span class="se"&gt;\&lt;/span&gt;
    --manual-cleanup-hook /opt/le-scripts/test/cleanup.sh &lt;span class="se"&gt;\&lt;/span&gt;
    -d &lt;span class="s1"&gt;&amp;#39;*.domain.tld&amp;#39;&lt;/span&gt;
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge &lt;span class="k"&gt;for&lt;/span&gt; domain.tld
Output from auth.sh:
------ AUTH ------
&lt;span class="nv"&gt;CERTBOT_VALIDATION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;39sbL18pMHYSusn0zZoenN3kUtJyq7DU-XnpzkFQdBA
&lt;span class="nv"&gt;CERTBOT_DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;domain.tld
------ AUTH ------

Waiting &lt;span class="k"&gt;for&lt;/span&gt; verification...
Cleaning up challenges
Output from cleanup.sh:
------ CLEANUP ------
&lt;span class="nv"&gt;CERTBOT_VALIDATION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;39sbL18pMHYSusn0zZoenN3kUtJyq7DU-XnpzkFQdBA
&lt;span class="nv"&gt;CERTBOT_DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;domain.tld
&lt;span class="nv"&gt;CERTBOT_AUTH_OUTPUT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;------ AUTH ------
&lt;span class="nv"&gt;CERTBOT_VALIDATION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;39sbL18pMHYSusn0zZoenN3kUtJyq7DU-XnpzkFQdBA
&lt;span class="nv"&gt;CERTBOT_DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;domain.tld
------ AUTH ------
------ CLEANUP ------

Failed authorization procedure. domain.tld &lt;span class="o"&gt;(&lt;/span&gt;dns-01&lt;span class="o"&gt;)&lt;/span&gt;: urn:ietf:params:acme:error:unauthorized :: The client lacks sufficient authorization :: No TXT record found at _acme-challenge.domain.tld

IMPORTANT NOTES:
 - The following errors were reported by the server:

   Domain: domain.tld
   Type:   unauthorized
   Detail: No TXT record found at _acme-challenge.domain.tld

   To fix these errors, please make sure that your domain name was
   entered correctly and the DNS A/AAAA record&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; that domain
   contain&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; the right IP address.
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Nous voyons ici que les scripts sont appelés avant la validation pour créer l’entrée DNS et après la validation pour la supprimer. Ces scripts reçoivent bien les variables d’environnement de &lt;code&gt;certbot&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="generation-de-certificat-wildcard-avec-dns-bind-local"&gt;Génération de certificat wildcard avec DNS bind local&lt;/h2&gt;
&lt;p&gt;Le répertoire &lt;code&gt;local-bind&lt;/code&gt; contient des scripts qui permettent d’ajouter l’entrée de validation dans des fichiers de zone bind accessible en local sur la machine qui émet le certificat.&lt;/p&gt;
&lt;p&gt;Ces scripts freezent la zone dns (pour éviter une rotation de clé dnssec lors de l’ajout de l’entrée), mettent à jour le numéro de série de la zone et ajoutent l’entrée (ou la suppriment pour le script de cleanup)&lt;/p&gt;
&lt;p&gt;Pour les utiliser, copiez le fichier &lt;code&gt;config.sh.example&lt;/code&gt; en &lt;code&gt;config.sh&lt;/code&gt; et adaptez le pour y indiquer l’emplacement de vos fichiers de zone, le format de leur nom (qui doit contenir le nom de domaine) ainsi que la chaine à rechercher pour trouver le serial de la zone.&lt;/p&gt;
&lt;p&gt;Vous pourrez ensuite générer votre certificat wildcard de la façon suivante :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; /opt/eff.org/certbot/venv/bin
$ ./certbot certonly &lt;span class="se"&gt;\&lt;/span&gt;
    --server https://acme-v02.api.letsencrypt.org/directory &lt;span class="se"&gt;\&lt;/span&gt;
    --manual-public-ip-logging-ok &lt;span class="se"&gt;\&lt;/span&gt;
    --manual &lt;span class="se"&gt;\&lt;/span&gt;
    --manual-auth-hook /opt/le-scripts/local-bind/auth.sh &lt;span class="se"&gt;\&lt;/span&gt;
    --manual-cleanup-hook /opt/le-scripts/local-bind/cleanup.sh &lt;span class="se"&gt;\&lt;/span&gt;
    -d &lt;span class="s1"&gt;&amp;#39;*.domain.tld&amp;#39;&lt;/span&gt;
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge &lt;span class="k"&gt;for&lt;/span&gt; domain.tld
Output from auth.sh:
Freeze zone
Update serial
Add challenge to zone file
Release zone
A zone reload and thaw was started.
Check the logs to see the result.
Wait &lt;span class="m"&gt;5&lt;/span&gt; seconds &lt;span class="k"&gt;for&lt;/span&gt; repplication to masters
Done

Waiting &lt;span class="k"&gt;for&lt;/span&gt; verification...
Cleaning up challenges
Output from cleanup.sh:
Freeze zone
Update serial
Remove challenge from zone file
Release zone
A zone reload and thaw was started.
Check the logs to see the result.
Done


IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/domain.tld/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/domain.tld/privkey.pem
   Your cert will expire on 2018-06-16. To obtain a new or tweaked
   version of this certificate in the future, simply run
   letsencrypt-auto again. To non-interactively renew *all* of your
   certificates, run &lt;span class="s2"&gt;&amp;quot;letsencrypt-auto renew&amp;quot;&lt;/span&gt;
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;s Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Il serait également possible de configurer bind pour accepter les mises à jour dynamiques (rfc2136) et utiliser le plugin &lt;code&gt;dns-rfc2136&lt;/code&gt; de certbot. Je vous le laisse en exercice ;)&lt;/p&gt;
&lt;h2 id="generation-de-certificat-wildcard-avec-dns-gandi-livedns"&gt;Génération de certificat wildcard avec DNS Gandi (LiveDNS)&lt;/h2&gt;
&lt;p&gt;Maintenant qu’on a bien joué avec nos scripts de test, voici un exemple plus près de la vie réelle pour la génération d’un certificat wildcard lorsque la zone DNS est hébergée chez Gandi.&lt;/p&gt;
&lt;p&gt;Il est indispensable que votre zone DNS soit hébergée sur la solution LiveDNS de gandi (v5) qui permet une mise à jour des enregistrement DNS instantanée contrairement à l’ancienne solution (v4). Dans l’ancienne version, il fallait plusieurs minutes pour que vos enregistrements DNS soient créés et ceci n’est pas compatible avec la validation de domaine.&lt;/p&gt;
&lt;p&gt;Ensuite, il vous suffit dans le répertoire &lt;code&gt;/opt/le-scripts/gandi-livedns&lt;/code&gt; de copier le fichier &lt;code&gt;config.py.example&lt;/code&gt; en &lt;code&gt;config.py&lt;/code&gt; et d’ajuster les paramètres :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;livedns_api = "https://dns.api.gandi.net/api/v5/"&lt;/code&gt; c’est le endpoint de l’API LiveDNS de Gandi. Il n’est habituellement pas nécessaire de modifier ce paramètre&lt;/li&gt;
&lt;li&gt;&lt;code&gt;livedns_apikey = "YOUR-KEY-HERE"&lt;/code&gt; Votre clé d’API LiveDNS que vous pourrez générer dans vos paramètres de compte à la rubrique “&lt;em&gt;Modification de mot de passe et configuration des restrictions d’accès&lt;/em&gt;“&lt;/li&gt;
&lt;li&gt;&lt;code&gt;livedns_sharing_id = None&lt;/code&gt; Si vos domaines ne sont pas rattachés directement à votre compte mais gérés dans une organisation, il faudra indiquer ici votre &lt;code&gt;sharing_id&lt;/code&gt; qui permet de gérer l’organisation à partir de votre compte. Vous le retrouverez dans l’URL du manager lorsque vous listez votre domaine sous la forme d'un GUID.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Une fois la configuration effectuée, il ne vous reste plus qu’à générer votre certificat :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; /opt/eff.org/certbot/venv/bin
$ ./certbot certonly &lt;span class="se"&gt;\&lt;/span&gt;
    --server https://acme-v02.api.letsencrypt.org/directory &lt;span class="se"&gt;\&lt;/span&gt;
    --manual-public-ip-logging-ok &lt;span class="se"&gt;\&lt;/span&gt;
    --manual &lt;span class="se"&gt;\&lt;/span&gt;
    --manual-auth-hook /opt/le-scripts/gandi-livedns/auth.py &lt;span class="se"&gt;\&lt;/span&gt;
    --manual-cleanup-hook /opt/le-scripts/gandi-livedns/cleanup.py &lt;span class="se"&gt;\&lt;/span&gt;
    -d &lt;span class="s1"&gt;&amp;#39;*.domain.tld&amp;#39;&lt;/span&gt;
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge &lt;span class="k"&gt;for&lt;/span&gt; domain.tld
Output from auth.py:
all good, entry created

Waiting &lt;span class="k"&gt;for&lt;/span&gt; verification...
Cleaning up challenges
Output from cleanup.py:
all good, entry deleted


IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/domain.tld/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/domain.tld/privkey.pem
   Your cert will expire on 2018-06-15. To obtain a new or tweaked
   version of this certificate in the future, simply run
   letsencrypt-auto again. To non-interactively renew *all* of your
   certificates, run &lt;span class="s2"&gt;&amp;quot;letsencrypt-auto renew&amp;quot;&lt;/span&gt;
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;s Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le
&lt;/pre&gt;&lt;/div&gt;


&lt;h2 id="generation-de-certificat-wildcard-avec-dns-ovh"&gt;Génération de certificat wildcard avec DNS OVH&lt;/h2&gt;
&lt;p&gt;Et si vos domaines sont hébergés chez OVH, c'est la même chose.&lt;/p&gt;
&lt;p&gt;On installe d'abord les prérequis :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ sudo apt-get install python3-dnspython
$ sudo pip3 install ovh
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Vous devez ensuite copier le fichier &lt;code&gt;/opt/le-scripts/ovh/ovh.conf.example&lt;/code&gt; en &lt;code&gt;/opt/le-scripts/ovh/ovh.conf&lt;/code&gt; et l'ajuster avec vos clés d'api.&lt;/p&gt;
&lt;p&gt;Et vous pouvez ensuite génèrer le certificat :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; /opt/eff.org/certbot/venv/bin/
$ ./certbot certonly &lt;span class="se"&gt;\&lt;/span&gt;
    --server https://acme-v02.api.letsencrypt.org/directory &lt;span class="se"&gt;\&lt;/span&gt;
    --manual-public-ip-logging-ok &lt;span class="se"&gt;\&lt;/span&gt;
    --manual &lt;span class="se"&gt;\&lt;/span&gt;
    --manual-auth-hook /opt/le-scripts/ovh/auth.py &lt;span class="se"&gt;\&lt;/span&gt;
    --manual-cleanup-hook /opt/le-scripts/ovh/cleanup.py &lt;span class="se"&gt;\&lt;/span&gt;
    -d &lt;span class="s1"&gt;&amp;#39;*.domain.tld&amp;#39;&lt;/span&gt;

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge &lt;span class="k"&gt;for&lt;/span&gt; domain.tld
Output from auth.py:
All good, DNS record created
Waiting &lt;span class="k"&gt;for&lt;/span&gt; record to be available on DNS servers
DNS record available on DNS server

Waiting &lt;span class="k"&gt;for&lt;/span&gt; verification...
Cleaning up challenges
Output from cleanup.py:
All good, DNS record deleted


IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/domain.tld/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/domain.tld/privkey.pem
   Your cert will expire on 2018-06-17. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   &lt;span class="s2"&gt;&amp;quot;certbot renew&amp;quot;&lt;/span&gt;
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;s Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le
&lt;/pre&gt;&lt;/div&gt;


&lt;h1 id="points-complementaires"&gt;Points complémentaires&lt;/h1&gt;
&lt;h2 id="emplacement-des-scripts-et-renouvelement"&gt;Emplacement des scripts et renouvèlement&lt;/h2&gt;
&lt;p&gt;Si vous devez déplacer les scripts sur votre système, le renouvèlement de certificat risque de ne pas les trouver, et donc d’échouer. Il vous faut alors mettre à jour le fichier de configuration du renouvèlement qui se trouve dans &lt;code&gt;/etc/letsencrypt/renewal/&amp;lt;domain&amp;gt;.conf&lt;/code&gt;&lt;/p&gt;
&lt;h2 id="delai-de-creation-de-lentree-dns"&gt;Délai de création de l’entrée DNS&lt;/h2&gt;
&lt;p&gt;Il est indispensable pour la validation automatique (et donc pour le renouvèlement) que votre système DNS permette de créer immédiatement une entrée DNS. S’il vous faut plusieurs minutes/heures/jours pour que l’entrée DNS soit créée, vous ne pourrez pas générer de certificat wildcard avec cette méthode. Bien que le protocole ACME semble semble permettre la validation asynchrone, je ne sais pas quelle est la durée de vie maximale du jeton d’authentification et le client certbot ne le permet pas, il vous faudra donc trouver ou coder un autre client ACME.&lt;/p&gt;
&lt;p&gt;Mais Hey, on est en 2018, il y a plein de super services DNS qui permettent de mettre en ligne immédiatement une entrée, avec un pilotage par api. Il est peut-être temps de changer de fournisseur DNS dans ce cas.&lt;/p&gt;
&lt;h2 id="et-la-securite-dans-tout-ca"&gt;Et la sécurité dans tout ça ?&lt;/h2&gt;
&lt;p&gt;Dans les exemples donnés, le serveur qui génère le certificat letsencrypt a un contrôle total sur la zone DNS. Il n’est pas souhaitable, en réalité, que le serveur web qui a besoin du certificat ait la possibilité de modifier tout le contenu de la zone DNS.
Dans ce cas, vous pouvez imaginer générer le certificat à partir d’une machine d’administration puis le pousser sur le serveur web qui en a besoin, ou développer une api interne accessible par le serveur web qui permette uniquement de gérer l’entrée &lt;code&gt;_acme-challenge&lt;/code&gt; et qui fera le relai vers le fournisseur DNS.&lt;/p&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Vous avez maintenant tous les éléments en main pour générer des certificats letsencrypt. 
Si vous vous posez encore des questions, n’hésitez pas à les laisser en commentaire, j’essaierai d’y répondre.&lt;/p&gt;</summary><category term="linux"></category><category term="letsencrypt"></category><category term="certificat"></category><category term="wildcard"></category><category term="gandi"></category><category term="livedns"></category><category term="route53"></category></entry><entry><title>Si on se faisait un petit certificat wildcard ? - Partie 1</title><link href="https://blog.blaisot.org/letsencrypt-wildcard-part1.html" rel="alternate"></link><published>2018-03-15T22:35:00+01:00</published><updated>2018-03-15T22:35:00+01:00</updated><author><name>sblaisot</name></author><id>tag:blog.blaisot.org,2018-03-15:letsencrypt-wildcard-part1.html</id><summary type="html">&lt;p&gt;Le 13 mars 2018, letsencrypt &lt;a href="https://community.letsencrypt.org/t/acme-v2-and-wildcard-certificate-support-is-live/55579"&gt;lançait&lt;/a&gt; enfin en production une fonctionnalité maintes fois réclamée : la possibilité de générer des certificats wildcard, c’est à dire des certificats valable pour tous les sous-domaines d’un domaine, de la forme *&lt;em&gt;.domaine.tld&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Habituellement, de tels certificats ne sont pas nécessaires pour un site web (puisqu’un certificat peut contenir plusieurs noms via l’utilisation des SAN, &lt;em&gt;Subject Alternate Name&lt;/em&gt;), cependant, il existe des cas où ils sont indispensable. Par exemple dans le cas d’un service pour lequel chaque utilisateur obtient une URL propre du style https://&lt;em&gt;username&lt;/em&gt;.service.tld. Dans ce cas, la liste peut être grande et n’est pas connue à l’avance et un certificat wildcard est nécessaire.&lt;/p&gt;
&lt;p&gt;Si letsencrypt fournit désormais des certificats wildcard, c’est pour couvrir ces cas de figure uniquement. Les certificats wildcard ne sont pas fait pour être déployés sur un ensemble de serveurs fournissant des services différents juste pour éviter de gérer des certificats différents. C’est une mauvaise pratique&lt;/p&gt;
&lt;h1 id="challenges"&gt;Challenges&lt;/h1&gt;
&lt;p&gt;Pour émettre un certificat, letsencrypt doit s’assurer que vous avez bien la main sur les ressources à certifier. Letsencrypt propose 3 types de challenge :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HTTP-01 : challenge par requête http, le plus couramment utilisé pour les certificats simples&lt;/li&gt;
&lt;li&gt;TLS-SNI-01 : challenge par présentation de certificat TLS. Ce challenge &lt;a href="https://community.letsencrypt.org/t/2018-01-11-update-regarding-acme-tls-sni-and-shared-hosting-infrastructure/50188"&gt;a été désactivé suite à des problèmes de sécurité&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;DNS-01 : challenge par requête DNS sur une entrée TXT dans le domaine.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Si dans le cas d’un site web, cette validation se résume généralement à vérifier que vous avez la main sur le serveur web, dans le cas d’un certificat wildcard il faut prouver que vous avez la main sur l’ensemble du domaine. Aussi, seul le challenge DNS-01 est possible pour des certificats wildcard letsencrypt, il faudra donc pouvoir éditer votre zone DNS pour commander ce type de certificat.&lt;/p&gt;
&lt;h1 id="fournisseurs-dns-geres"&gt;Fournisseurs DNS gérés&lt;/h1&gt;
&lt;p&gt;Le client letsencrypt certbot gère nativement les fournisseurs de service DNS suivants :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AWS Route53&lt;/li&gt;
&lt;li&gt;Cloudflare&lt;/li&gt;
&lt;li&gt;CloudXNS&lt;/li&gt;
&lt;li&gt;DigitalOcean&lt;/li&gt;
&lt;li&gt;DNSimple&lt;/li&gt;
&lt;li&gt;DNS Made Easy&lt;/li&gt;
&lt;li&gt;Google Cloud DNS&lt;/li&gt;
&lt;li&gt;LuaDNS&lt;/li&gt;
&lt;li&gt;NS1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Certbot permet aussi de gérer les serveurs DNS dynamiques conformes à la &lt;a href="https://tools.ietf.org/html/rfc2136"&gt;RFC 2136&lt;/a&gt; comme par exemple bind.&lt;/p&gt;
&lt;p&gt;Il est également possible d’émettre un certificat wildcard en éditant manuellement la zone DNS. C’est utile pour tester, en revanche, le renouvèlement automatique du certificat ne sera pas possible et il vous faudra dans ce cas renouveler l’opération tous les 3 mois (durée de vie maximum des certificats letssencrypt).&lt;/p&gt;
&lt;p&gt;Enfin, outre la possibilité de développer un plugin à certbot pour gérer un autre fournisseur (et cela arrivera, des gens en feront, mais il y en a peu pour l’instant principalement parce que le challenge HTTP-01 était suffisant jusqu’à présent), il est également possible de fournir à certbot un script/programme à lancer pour créer et supprimer l’entrée DNS de challenge et y faire ce qu’on veut.&lt;/p&gt;
&lt;p&gt;Nous ne couvrirons pas ici l’ensemble des fournisseurs de DNS, mais je vais vous présenter l’émission de certificats wildcard letsencrypt avec édition manuelle de la zone DNS et dans un second article l’émission de certificat wildcard pour un domaine géré sur AWS route53 ainsi que l’utilisation de scripts maison d’édition de zone pour gérer un provider non disponible. Je prendrai l’exemple de Gandi pour cela.&lt;/p&gt;
&lt;h1 id="prerequis"&gt;Prérequis&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Vous devrez disposer du client &lt;a href="https://certbot.eff.org/"&gt;certbot&lt;/a&gt; en version 0.22.0 au minimum. à l’heure où j’écris ces lignes, cette version n’est pas encore présente sur les dépots debian ou ubuntu mais nous allons voir comment l’installer, éventuellement en parallèle d’une autre version que vous utilisez déjà. Pour vérifier votre version de certbot, utilisez &lt;code&gt;certbot --version&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;La possibilité d’éditer votre zone DNS. De préférence via une API ou à défaut automatisable par scripting.&lt;/li&gt;
&lt;li&gt;Un peu de patience et de persévérance, même si j’ai l’outrecuidance de penser que ces quelques lignes les allègeront…&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="installation-de-certbot-0220"&gt;Installation de certbot 0.22.0&lt;/h1&gt;
&lt;p&gt;Ces instructions permettent d’installer certbot sur la plupart des systèmes unix/linux dans /opt y compris si vous avez déjà une autre version de certbot installée par les packages de votre distribution sans y toucher. Cela vous permettra de tester la génération de certificat wildcard pour être prêt dès que cette version sera disponible dans votre repo/ppa préféré.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Créez un répertoire /opt/certbot pour le wrapper de téléchargement/mise à jour de certbot&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ mkdir /opt/certbot
$ &lt;span class="nb"&gt;cd&lt;/span&gt; /opt/certbot
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Téléchargez le wrapper sur le site de certbot&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ wget https://dl.eff.org/certbot-auto
$ chmod a+x certbot-auto
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Lancez l’installation&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ ./certbot-auto --install-only
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Et voilà, certbot 0.22.0 (ou plus récent) est installé dans &lt;code&gt;/opt/eff.org/certbot&lt;/code&gt; comme nous le prouve la commande suivante :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ /opt/eff.org/certbot/venv/bin/certbot --version
certbot 0.22.0
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Le seul inconvénient de cette méthode si vous utilisez déjà un certbot installé par le package de votre repo/ppa préféré et que vous avez mis en place un renouvèlement automatique est que cette version antérieure à 0.22.0 sera incapable de renouveler automatiquement vos certificats. Cependant, cela laisse 3 mois pour que ce package soit mis à jour en version 0.22.0, ce qui ne devrait plus tarder désormais.&lt;/p&gt;
&lt;p&gt;Note complémentaire : si vous souhaitez désinstaller votre package certbot ou letsencrypt (encore plus ancien), faites une sauvegarde de votre &lt;code&gt;/etc/letsencrypt&lt;/code&gt; avant. En effet, un &lt;code&gt;apt-get purge certbot&lt;/code&gt; a la désagréable habitude de supprimer ce répertoire et vous predriez tous vos crtificats.&lt;/p&gt;
&lt;h1 id="generation-de-certificat-wildcard-avec-edition-manuelle-de-zone-dns"&gt;Génération de certificat wildcard avec édition manuelle de zone DNS&lt;/h1&gt;
&lt;p&gt;Pour générer un certificat en éditant manuellement la zone DNS, c’est aussi simple que :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; /opt/eff.org/certbot/venv/bin/
$ ./certbot certonly --server https://acme-v02.api.letsencrypt.org/directory &lt;span class="se"&gt;\&lt;/span&gt;
                     --manual -d &lt;span class="s1"&gt;&amp;#39;*.domain.tld&amp;#39;&lt;/span&gt;
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge &lt;span class="k"&gt;for&lt;/span&gt; domain.tld

-------------------------------------------------------------------------------
NOTE: The IP of this machine will be publicly logged as having requested this
certificate. If you&lt;span class="s1"&gt;&amp;#39;re running certbot in manual mode on a machine that is not&lt;/span&gt;
&lt;span class="s1"&gt;your server, please ensure you&amp;#39;&lt;/span&gt;re okay with that.

Are you OK with your IP being logged?
-------------------------------------------------------------------------------
&lt;span class="o"&gt;(&lt;/span&gt;Y&lt;span class="o"&gt;)&lt;/span&gt;es/&lt;span class="o"&gt;(&lt;/span&gt;N&lt;span class="o"&gt;)&lt;/span&gt;o: y

-------------------------------------------------------------------------------
Please deploy a DNS TXT record under the name
_acme-challenge.domain.tld with the following value:

6CmoURMbv3F14hJdzR8zqXrhcYJeKWJEhT8xZcz4gUY

Before continuing, verify the record is deployed.
-------------------------------------------------------------------------------
Press Enter to Continue
Waiting &lt;span class="k"&gt;for&lt;/span&gt; verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/domain.tldu/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/domain.tld/privkey.pem
   Your cert will expire on 2018-06-13. To obtain a new or tweaked
   version of this certificate in the future, simply run
   letsencrypt-auto again. To non-interactively renew *all* of your
   certificates, run &lt;span class="s2"&gt;&amp;quot;letsencrypt-auto renew&amp;quot;&lt;/span&gt;
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;s Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Voici les options utilisées :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--server https://acme-v02.api.letsencrypt.org/directory&lt;/code&gt;  : On utilise l’API ACME v2&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--manual&lt;/code&gt; on va créer l’entrée DNS pour le challenge manuellement&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-d '*.domain.tld'&lt;/code&gt; le sujet du certificat qu’on souhaite émettre&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Et le détail de ce qui s’est passé et des actions a effectuer :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tout d’abord, on aura des logs, c’est là qu’il faudra aller voir si quelque chose se passe mal&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Saving debug log to /var/log/letsencrypt/letsencrypt.log
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Nous avons demandé à créer les entrées pour le challenge manuellement (&lt;code&gt;--manual&lt;/code&gt;) et ne souhaitons pas que certbot installe le certificat pour nous dans notre serveur web (&lt;code&gt;certonly&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Plugins selected: Authenticator manual, Installer None
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;L’adresse IP de la machine qui initie la demande de certificat est enregistrée et disponible publiquement dans le cadre de la transparence sur l’émission des certificats. Si vous refuser, vous ne pourrez pas obtenir de certificat de la part de letsencrypt. Ce message et la question peuvent être évitée en ajoutant l’option &lt;code&gt;--manual-public-ip-logging-ok&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;-------------------------------------------------------------------------------
NOTE: The IP of this machine will be publicly logged as having requested this
certificate. If you&amp;#39;re running certbot in manual mode on a machine that is not
your server, please ensure you&amp;#39;re okay with that.

Are you OK with your IP being logged?
-------------------------------------------------------------------------------
(Y)es/(N)o: y
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Vient ensuite la phase de challenge&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;-------------------------------------------------------------------------------
Please deploy a DNS TXT record under the name
_acme-challenge.domain.tld with the following value:

6CmoURMbv3F14hJdzR8zqXrhcYJeKWJEhT8xZcz4gUY

Before continuing, verify the record is deployed.
-------------------------------------------------------------------------------
Press Enter to Continue
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Il ne vous reste plus qu’à ajouter dans votre zone DNS une entrée de type TXT de nom &lt;code&gt;_acme-challenge&lt;/code&gt; et dont la valeur vous est fournie par letsencrypt (ici &lt;code&gt;6CmoURMbv3F14hJdzR8zqXrhcYJeKWJEhT8xZcz4gUY&lt;/code&gt;)
Par exemple, pour bind :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;_acme-challenge        IN    TXT        6CmoURMbv3F14hJdzR8zqXrhcYJeKWJEhT8xZcz4gUY
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Si nécessaire, attendez le temps de la bonne mise en place de votre entrée DNS et de sa propagation si votre DNS n’est pas très véloce, puis appuyez sur entrée et certbot se charge de demander à letsencrypt de vérifier le challenge.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Enfin, si tout s’est bien passé, votre certificat est disponible dans &lt;code&gt;/etc/letsencrypt/live/domain.tld&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Voilà pour cette première partie qui, je l’espère, vous aura permis de générer votre premier certificat wildcard. Dans un &lt;a href="letsencrypt-wildcard-part2.html"&gt;second article&lt;/a&gt; je détaille la génération de certificat letsencrypt avec édition automatique de la zone pour le service DNS AWS route53 ainsi que l’utilisation de script personnels pour l’édition de la zone DNS et nous appliquerons cette dernière méthode pour des domaines hébergés sur les DNS de Gandi et d'OVH.&lt;/p&gt;</summary><category term="linux"></category><category term="letsencrypt"></category><category term="certificat"></category><category term="wildcard"></category></entry><entry><title>Multi-diffusez vos tableaux de bord, de manière centralisée, sans fil et à faible coût avec Raspberry Pi, dashkiosk et Chromecast</title><link href="https://blog.blaisot.org/raspi-dashkiosk-chromecast.html" rel="alternate"></link><published>2017-09-20T18:00:00+02:00</published><updated>2017-09-20T18:00:00+02:00</updated><author><name>sblaisot</name></author><id>tag:blog.blaisot.org,2017-09-20:raspi-dashkiosk-chromecast.html</id><summary type="html">

&lt;p&gt;Ok, le titre sonnait mieux en anglais : &lt;em&gt;Low-cost centralized wireless dashboard multicasting with Raspberry Pi, dashkiosk and Chromecast&lt;/em&gt;. Mais la ligne éditoriale de ce blog est en Français...&lt;/p&gt;
&lt;p&gt;Les équipes informatiques sont friandes des écrans sur les murs qui diffusent toutes sortes de tableaux de bord, que ce soit l'état de la chaine d'intégration continue, le taux de passage des tests ou les métriques de supervision de la production. Ces dernières années ont vu fleurir les écrans sur les murs des open-spaces. Généralement contrôlés par des &lt;a href="https://fr.wikipedia.org/wiki/Syst%C3%A8me_sur_une_puce"&gt;SOC&lt;/a&gt; (Raspberry Pi, Odroid, ...).
Cette solution peu onéreuse a toutefois quelques inconvénients. Notamment, cela fait un OS de plus à administrer pour chaque écran, la fiabilité est moyenne (combien de prise de main à distance sur le Raspberry Pi par an et par écran ?) et surtout, chaque solution d'affichage est autonome, avec ses avantages, mais aussi ses inconvénients.&lt;/p&gt;
&lt;p&gt;La solution que je vous propose aujourd'hui a pour objectif :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;De diffuser vos tableaux de bord (accessibles en HTTP/HTTPS) sur plusieurs écrans&lt;/li&gt;
&lt;li&gt;De diffuser du contenu sans fil (via Wi-Fi)&lt;/li&gt;
&lt;li&gt;D'être gérée de manière centralisée&lt;/li&gt;
&lt;li&gt;D'être d'une fiabilité déconcertante&lt;/li&gt;
&lt;li&gt;De pouvoir ajouter un écran très facilement, rapidement, sans connaissances particulière de l'administration système&lt;/li&gt;
&lt;li&gt;De couter moins cher qu'un Raspberry Pi pour chaque écran&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Elle peut également servir dans d'autres contextes, par exemple gérer les différents écrans publicitaires d'une boutique pour de la &lt;a href="https://fr.wikipedia.org/wiki/Affichage_dynamique"&gt;signalétique numérique&lt;/a&gt;&lt;/p&gt;


&lt;h1 id="tour-dhorizon"&gt;Tour d'horizon&lt;/h1&gt;
&lt;p&gt;Je vous propose donc d'utiliser un Raspberry Pi pour gérer vos affichages de manière centralisée (c'est à dire pouvoir simplement choisir quel(s) tableau(x) de bord seront affichés sur quels écrans) en utilisant le logiciel dashkiosk et d'utiliser des Chromecast pour la diffusion.&lt;/p&gt;
&lt;p&gt;dashkiosk peut être installé sur n'importe quelle machine, mais le Raspberry est l'une des moins cher.
Ce logiciel en nodejs permet de gérer chaque écran et de décider ce qui sera affiché dessus (quelles URL), de gérer l'affichage en fonction de l'heure ou du jour, de réaliser un cycle entre différentes URL, etc...&lt;/p&gt;
&lt;p&gt;&lt;img alt="img1" src="/static/img/dashkiosk/overview.png" title="Vue d'ensemble" /&gt;&lt;/p&gt;
&lt;p&gt;Un kit de démarrage Raspberry Pi 3 coute environ 55€ TTC (Raspberry Pi + boitier + alimentation + sdcard).
On trouve des Chromecast de première génération sur ebay pour environ 10€ port compris. c'est amplement suffisant.&lt;/p&gt;
&lt;p&gt;Cela nous fait donc un cout total d'environ 55€ + 10€ * (nombre d'écran).&lt;/p&gt;
&lt;h1 id="dashkiosk"&gt;Dashkiosk&lt;/h1&gt;
&lt;p&gt;Dashkiosk est une solution de gestion d'affichage multi-écrans. La video ci-dessous vous présente en détail son fonctionnement :&lt;/p&gt;
&lt;div class="video-container"&gt;&lt;iframe width="853" height="480" src="https://www.youtube-nocookie.com/embed/Vb4BvEzoYOU?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/div&gt;

&lt;h2 id="installation"&gt;Installation&lt;/h2&gt;
&lt;p&gt;Nous allons commencer par installer nodejs. Comme dashkiosk s'attend à avoir nodejs accessible par la commande &lt;code&gt;node&lt;/code&gt;, nous demandons aussi à &lt;code&gt;alternatives&lt;/code&gt; de gérer un lien symbolique pour nous.
Nous installons également les prérequis à dashkiosk.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ aptitude install nodejs npm
$ update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10
$ aptitude install git libavahi-compat-libdnssd-dev libsqlite3-dev libjpeg-progs optipng gifsicle autoconf dh-autoreconf
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Téléchargez dashkiosk depuis github et configurez le tout.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ curl -sL -o - &lt;span class="s1"&gt;&amp;#39;https://github.com/vincentbernat/dashkiosk/archive/master.tar.gz&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; tar -C /opt -zxvf -
$ mv /opt/dashkiosk-master /opt/dashkiosk
$ &lt;span class="nb"&gt;cd&lt;/span&gt; /opt/dashkiosk
$ npm install -g bower grunt-cli
$ npm install
$ grunt
$ &lt;span class="nb"&gt;cd&lt;/span&gt; dist &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm install --production
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Troll mode : oui oui, on utilise un gestionnaire de paquets (aptitude) pour installer un gestionnaire de paquets (npm) qui nous permet d'installer un gestionnaire de paquets (bower). C'est trop cool, en fait, NodeJS ;)&lt;/p&gt;
&lt;p&gt;Démarrons dashkiosk et testons avec un navigateur si cela fonctionne :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; /opt/dashkiosk/dist
$ node server.js --environment production
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Vous pouvez ensuite avec un navigateur vous rendre à l'URL &lt;code&gt;http://&amp;lt;IP de votre raspberry&amp;gt;:9400/admin&lt;/code&gt; pour accéder à l'interface d'administration et avec un autre onglet à l'adresse &lt;code&gt;http://&amp;lt;IP de votre raspberry&amp;gt;:9400/receiver&lt;/code&gt; pour en faire un écran d'affichage.&lt;/p&gt;
&lt;p&gt;Une fois votre test effectué, vous pouvez quitter dashkiosk (CTRL-C)&lt;/p&gt;
&lt;h2 id="demarrage-automatique"&gt;Démarrage automatique&lt;/h2&gt;
&lt;p&gt;Bon, c'est chouette de pouvoir lancer à la main dashkiosk, mais ce serait mieux qu'il se lance tout seul comme tous les autres démons. &lt;code&gt;systemd&lt;/code&gt; va gérer cela pour nous.&lt;/p&gt;
&lt;p&gt;Créez un utilisateur dashkiosk qui sera dédié au lancement de dashkiosk:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ adduser --home /opt/dashkiosk/ --shell /usr/sbin/nologin --no-create-home --disabled-login --gecos &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt; dashkiosk
$ chown -R dashkiosk: /opt/dashkiosk/dist/
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Puis créez un fichier &lt;code&gt;/etc/systemd/system/dashkiosk.service&lt;/code&gt; avec le contenu suivant :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Dashkiosk dashboard admin&lt;/span&gt;

&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/bin/nodejs server.js --environment production&lt;/span&gt;
&lt;span class="na"&gt;StandardOutput&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;null&lt;/span&gt;
&lt;span class="na"&gt;StandardError&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;syslog&lt;/span&gt;
&lt;span class="na"&gt;Restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;always&lt;/span&gt;
&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;dashkiosk&lt;/span&gt;
&lt;span class="na"&gt;Group&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;dashkiosk&lt;/span&gt;
&lt;span class="na"&gt;WorkingDirectory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/opt/dashkiosk/dist/&lt;/span&gt;

&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Vous aurez remarqué qu'on supprime la sortie standard. En effet, dashkiosk est très verbeux et j'ai rempli un disque de 15Go en moins d'une semaine en l'envoyant dans syslog. Il est toujours possible de remplacer &lt;code&gt;null&lt;/code&gt; par &lt;code&gt;syslog&lt;/code&gt; temporairement pour débugguer ultérieurement.&lt;/p&gt;
&lt;p&gt;Il ne reste plus ensuite qu'à demander à systemd de prendre en compte ce fichier et à lancer dashkiosk :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; dashkiosk
$ systemctl start dashkiosk
&lt;/pre&gt;&lt;/div&gt;


&lt;h1 id="chromecast"&gt;Chromecast&lt;/h1&gt;
&lt;p&gt;Nous allons supposer ici que votre chromecast est déjà configurée et fonctionnelle, c'est un jeu d'enfant en suivant les instructions à l'écran.&lt;/p&gt;
&lt;p&gt;Comme la Chromecast est découverte en utilisant le protocole DNS multicast (mDNS), le Raspberry Pi et la Chromecast doivent obligatoirement être dans le même réseau pour que cela fonctionne.&lt;/p&gt;
&lt;p&gt;Nous allons configurer notre Raspberry Pi pour qu'il fasse de la résolution DNS multicast (ZeroConf/Apple Bonjour/Microsoft LLMNR).&lt;/p&gt;
&lt;p&gt;D'abord, installez les packages nécessaires :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ aptitude install avahi-utils libnss-mdns
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;puis éditez le fichier &lt;code&gt;/etc/nsswitch.conf&lt;/code&gt; et remplacez la ligne qui commence par &lt;code&gt;hosts&lt;/code&gt; par ce contenu :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;hosts&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;          &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="n"&gt;mdns4_minimal&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NOTFOUND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;dns&lt;/span&gt; &lt;span class="n"&gt;mdns4&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Il n'y a plus qu'à tester manuellement que cela fonctionne. Nous lançons d'abord une recherche de chromecast :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ avahi-browse -r _googlecast._tcp
+  wlan0 IPv4 Chromecast-Ultra-7f532001624a95c2f74e7b44d690c056 _googlecast._tcp     &lt;span class="nb"&gt;local&lt;/span&gt;
&lt;span class="o"&gt;=&lt;/span&gt;  wlan0 IPv4 Chromecast-Ultra-7f532001624a95c2f74e7b44d690c056 _googlecast._tcp     &lt;span class="nb"&gt;local&lt;/span&gt;
   &lt;span class="nv"&gt;hostname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;7f532001-624a-95c2-f74e-7b44d690c056.local&lt;span class="o"&gt;]&lt;/span&gt;
   &lt;span class="nv"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;192.168.1.2&lt;span class="o"&gt;]&lt;/span&gt;
   &lt;span class="nv"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;8009&lt;span class="o"&gt;]&lt;/span&gt;
   &lt;span class="nv"&gt;txt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;rs=&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;nf=1&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;bs=FA8FCA7ED164&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;st=0&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;ca=4101&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;fn=Chromecast&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;ic=/setup/icon.png&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;md=Chromecast Ultra&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;ve=05&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;rm=BE1C2E8914AAF2BB&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;cd=D7FBF1741973D5D9085B37B99AF75FE1&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;id=7f532001624a95c2f74e7b44d690c056&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;avahi-browse&lt;/code&gt; découvre bien une chromecast. Relevez le contenu de hostname (ici &lt;code&gt;7f532001-624a-95c2-f74e-7b44d690c056.local&lt;/code&gt;) puis essayez de récupérer son adresse IP :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ getent hosts 7f532001-624a-95c2-f74e-7b44d690c056.local
192.168.1.2     7f532001-624a-95c2-f74e-7b44d690c056.local
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Si vous obtenez bien l'adresse IP de votre Chromecast, c'est que tout fonctionne, votre Raspberry Pi peut découvrir votre Chromecast et communiquer avec.&lt;/p&gt;
&lt;p&gt;Editez ensuite le fichier &lt;code&gt;/opt/dashkiosk/dist/lib/config.js&lt;/code&gt; et modifiez la section &lt;code&gt;chromecast&lt;/code&gt; comme ceci :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;// Chromecast
chromecast: {
  enabled: true,
  receiver: &amp;#39;http://&amp;lt;IP de votre raspberry&amp;gt;:9400/receiver&amp;#39;,
  app: &amp;#39;5E7A2C2C&amp;#39;
},
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;en remplaçant &lt;code&gt;&amp;lt;IP de votre raspberry&amp;gt;&lt;/code&gt; par l'IP de votre Raspberry Pi. Cela permet d'indiquer aux clients Chromecast l'URL à charger.&lt;/p&gt;
&lt;p&gt;Il suffit ensuite de relancer dashkiosk :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ systemctl restart dashkiosk
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Vous devriez alors voir aparaitre votre Chromecast comme nouvel écran dans l'interface d'administration de dashkiosk. Il suffit de le placer dans un groupe pour qu'il charge les dashboard sélectionnés&lt;/p&gt;
&lt;h1 id="ajout-dun-ecran"&gt;Ajout d'un écran&lt;/h1&gt;
&lt;p&gt;Ajouter un écran à la solution est d'une simplicité enfantine. Il suffit de configurer la Chromecast et de la connecter au même réseau que le Raspberry Pi, dashkiosk la reconnait alors automatiquement et il n'y a plus qu'à l'ajouter dans le bon groupe pour que l'écran commence à diffuser son contenu.&lt;/p&gt;
&lt;h1 id="et-la-securite-dans-tout-ca"&gt;Et la sécurité dans tout ça ?&lt;/h1&gt;
&lt;h2 id="controle-dacces"&gt;Contrôle d'accès&lt;/h2&gt;
&lt;h3 id="a-ladministration-de-dashkiosk"&gt;à l'administration de dashkiosk&lt;/h3&gt;
&lt;p&gt;Comme on ne veut pas que n'importe qui sur le réseau puisse modifier l'affichage sur nos écrans, nous devons protéger l'accès à l'interface d'administration de dashkiosk.&lt;/p&gt;
&lt;p&gt;Pour ajouter du contrôle d'accès à dashkiosk, il suffit d'éditer le fichier &lt;code&gt;/opt/dashkiosk/dist/lib/config.js&lt;/code&gt; et de modifier la section &lt;code&gt;auth&lt;/code&gt; pour ajouter un utilisateur et un mot de passe d'accès à l'administration de dashkiosk :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;// Auth
auth: {
  enabled: true,
  realm: &amp;#39;Dashkiosk&amp;#39;,
  username: &amp;#39;myuser&amp;#39;,
  password: &amp;#39;mypasswd&amp;#39;
},
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Il faut ensuite relancer dashkiosk pour la prise en compte de ces nouveaux paramètres :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ systemctl restart dashkiosk
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Cependant, cette approche présente un inconvénient : l'URL de visualisation est également protégée, il faut donc modifier l'URL des clients sous la forme &lt;code&gt;http://user@password:&amp;lt;IP de votre raspberry&amp;gt;:9400/receiver&lt;/code&gt;. C'est moche d'abord parce qu'on véhicule un mot de passe sur une session non chiffrée (HTTP) et d'autre part parce que la chromecast affiche l'url lors du chargement. bof bof.&lt;/p&gt;
&lt;p&gt;Une meilleure solution serait d'installer un serveur web en frontal de dashkiosk qui ne protège que la partie administration de dashkiosk. Je vous laisse cette partie en exercice.&lt;/p&gt;
&lt;h3 id="aux-chromecast"&gt;aux Chromecast&lt;/h3&gt;
&lt;p&gt;Il est préférable, pour éviter que tout le monde joue avec les chromecast de les protéger.&lt;/p&gt;
&lt;p&gt;Dans les paramètres de votre Chromecast (contrôlable par l'application Google Home sur un téléphone android), assurez vous que le paramètre suivant est décoché :&lt;/p&gt;
&lt;p&gt;&lt;img alt="img1" src="/static/img/dashkiosk/chromecast_settings.png" title="Paramètre Chromecast" /&gt;&lt;/p&gt;
&lt;p&gt;Vous pouvez également utiliser un réseau dédié pour connecter vos Chromecast. Ainsi, personne ne pourra prendre la main dessus. Le Raspberry Pi pourra alors se connecter à ce réseau avec son interface Wi-Fi et au réseau de l'entreprise grâce à son interface RJ45 pour l'administration de la solution.&lt;/p&gt;
&lt;p&gt;Je vous laisse aussi en exercice ce point ;)&lt;/p&gt;
&lt;h2 id="disponibilite"&gt;Disponibilité&lt;/h2&gt;
&lt;p&gt;Cette solution a l'avantage de la robustesse. Si un écran &lt;em&gt;plante&lt;/em&gt;, il suffit de relancer la Chromecast (débrancher/rebrancher). Dashkiosk la redécouvre et reconnecte les chromecast automatiquement.&lt;/p&gt;
&lt;p&gt;On peut même avoir en stock une Chromecast supplémentaire pour effectuer un remplacement ultra rapide en cas de défaillance. c'est beaucoup plus simple à configurer que de réinstaller un Raspberry Pi pour le coller derrière un écran...&lt;/p&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Voilà une solution à moindre cout, fiable, qui sera utile aussi bien pour la gestion de multiples écrans à partir d'un point central que pour la gestion d'un seul écran lorsque l'unité "intelligente" doit être déportée loin de l'affichage.&lt;/p&gt;</summary><category term="raspi"></category><category term="raspberry"></category><category term="dashkiosk"></category><category term="dashboard"></category><category term="chromecast"></category></entry><entry><title>Time-series sur Raspberry Pi avec la stack TICK</title><link href="https://blog.blaisot.org/raspi-timeseries-tick-stack.html" rel="alternate"></link><published>2017-09-18T15:00:00+02:00</published><updated>2017-09-18T15:00:00+02:00</updated><author><name>sblaisot</name></author><id>tag:blog.blaisot.org,2017-09-18:raspi-timeseries-tick-stack.html</id><summary type="html">

&lt;p&gt;Aujourd'hui, nous allons voir comment installer la pile TICK (Telegraf, InfluxDB, Chronograf et Kapacitor) sur un Raspberry Pi 3 sous Raspbian Lite pour jouer avec les séries temporelles (time-series) à la maison.&lt;/p&gt;
&lt;p&gt;Les &lt;a href="https://fr.wikipedia.org/wiki/S%C3%A9rie_temporelle"&gt;séries temporelles&lt;/a&gt; sont une suite de valeurs numériques évoluant au cours du temps. Elles sont particulièrement adaptées pour manipuler des mesures comme la température, la charge CPU d'une machine, etc...&lt;/p&gt;
&lt;p&gt;On s'attachera ici à déployer la pile uniquement, à injecter des données provenant du Raspberry (monitoring) et à afficher un dashboard de ces données.
En revanche, nous n'aborderons pas en détail la configuration, ni la sécurisation de la pile (gestion des droits notamment), ni encore la scalabilité de la solution, je laisse ça pour un prochain article.&lt;/p&gt;
&lt;div class="toc"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#la-pile-tick"&gt;La pile TICK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#installation"&gt;Installation&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#ajout-du-depot-influxdatacom"&gt;Ajout du dépot InfluxData.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#installation-dinfluxdb"&gt;Installation d'InfluxDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#installation-de-chronograf"&gt;Installation de Chronograf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#installation-de-telegraf"&gt;Installation de Telegraf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#installation-de-kapacitor"&gt;Installation de Kapacitor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#ajoutons-une-source-de-donnees"&gt;Ajoutons une source de données&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;


&lt;h1 id="la-pile-tick"&gt;La pile TICK&lt;/h1&gt;
&lt;p&gt;La &lt;a href="https://www.influxdata.com/time-series-platform/"&gt;pile TICK&lt;/a&gt; est une pile logicielle dédiée à la manipulation des séries temporelles. Elle se compose des 4 éléments suivants :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Telegraf qui est un agent de collecte des données doté de nombreux plugins de collecte ainsi que de stockage, &lt;/li&gt;
&lt;li&gt;InfluxDB qui est la base de données de stockage des séries temporelles, &lt;/li&gt;
&lt;li&gt;Chronograf, l'interface graphique de visualisation des données, &lt;/li&gt;
&lt;li&gt;Kapacitor qui traite les données et déclenche des actions ou des alertes suivant les règles que vous lui avez établies. Il peut alerter par SMTP, slack, PagerDuty, Telegram et plein d'autre moyens encore.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="img1" src="/static/img/raspi-tick-stack/InfluxData_TICK-1.png" title="La pile TICK" /&gt;&lt;/p&gt;
&lt;h1 id="installation"&gt;Installation&lt;/h1&gt;
&lt;p&gt;Dans la suite de cet article, nous supposons que vous installez sur un OS raspbian lite, mais c'est probablement identique sur l'ensemble des distributions dérivées de debian.&lt;/p&gt;
&lt;h2 id="ajout-du-depot-influxdatacom"&gt;Ajout du dépot InfluxData.com&lt;/h2&gt;
&lt;p&gt;En premier lieu, nous allons ajouter le dépot influxdata à notre Raspberry Pi&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ sudo &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;deb https://repos.influxdata.com/debian &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;grep -e &lt;span class="s1"&gt;&amp;#39;^VERSION=&amp;#39;&lt;/span&gt; /etc/os-release &lt;span class="p"&gt;|&lt;/span&gt; sed -e &lt;span class="s1"&gt;&amp;#39;s/^.*(\(.*\)).*$/\1/&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; stable&amp;quot;&lt;/span&gt; &amp;gt; /etc/apt/sources.list.d/influxdb.list
$ sudo curl -sL https://repos.influxdata.com/influxdb.key &lt;span class="p"&gt;|&lt;/span&gt; apt-key add -
$ sudo aptitude update
&lt;/pre&gt;&lt;/div&gt;


&lt;h2 id="installation-dinfluxdb"&gt;Installation d'InfluxDB&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ sudo aptitude install influxdb influxdb-client
$ sudo systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; influxdb
$ sudo systemctl start influxdb
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Vous pouvez ensuite tester que la base est bien démarrée avec la commande suivante :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ curl &lt;span class="s2"&gt;&amp;quot;http://localhost:8086/query?q=show+databases&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;results&amp;quot;&lt;/span&gt;:&lt;span class="o"&gt;[{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;statement_id&amp;quot;&lt;/span&gt;:0,&lt;span class="s2"&gt;&amp;quot;series&amp;quot;&lt;/span&gt;:&lt;span class="o"&gt;[{&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;:&lt;span class="s2"&gt;&amp;quot;databases&amp;quot;&lt;/span&gt;,&lt;span class="s2"&gt;&amp;quot;columns&amp;quot;&lt;/span&gt;:&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,&lt;span class="s2"&gt;&amp;quot;values&amp;quot;&lt;/span&gt;:&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;_internal&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]]}]}]}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Le résultat vous indique qu'il existe une base nommée &lt;code&gt;_internal&lt;/code&gt;. C'est tout bon.&lt;/p&gt;
&lt;p&gt;Si vous obtenez au premier lancement de la commande curl le résultat suivant :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;{&amp;quot;results&amp;quot;:[{&amp;quot;statement_id&amp;quot;:0,&amp;quot;series&amp;quot;:[{&amp;quot;name&amp;quot;:&amp;quot;databases&amp;quot;,&amp;quot;columns&amp;quot;:[&amp;quot;name&amp;quot;]}]}]}
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Pas de panique. Cela peut arriver la première fois, quand InfluxDB n'a encore reçu aucune commande, la base interne n'existe pas. Au second appel de curl, vous devriez voie que la base d edonnées interne a été créée.&lt;/p&gt;
&lt;h2 id="installation-de-chronograf"&gt;Installation de Chronograf&lt;/h2&gt;
&lt;p&gt;Chronograf est l'interface utilisateur de la pile TICK.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ sudo aptitude install chronograf
$ sudo systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; chronograf
$ sudo systemctl start chronograf
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Vous pouvez ensuite vous rendre avec votre navigateur à l'adresse &lt;code&gt;http://&amp;lt;IP de votre raspberry&amp;gt;:8888/&lt;/code&gt;.
L'écran de configuration de chronograf vous est alors présenté. Il faut entrer les informations de connexion à InfluxDB.
Nous n'avons pas mis en place de gestion de droit sur InfluxDB, vous pouvez donc laisser vide les champs utilisateur de mot de passe.&lt;/p&gt;
&lt;p&gt;&lt;img alt="img2" src="/static/img/raspi-tick-stack/Chronograf2.png" title="Ecran de configuration de chronograf" /&gt;&lt;/p&gt;
&lt;p&gt;Et voilà, vous pouvez commencer à jouer avec l'interface de visualisation des données. Il y a déjà les données de métrologie de la base de données influxdb (nombre de requêtes exécutées, durée des requêtes, nombre d'accès http, etc...) dans la base de données "_internal.monitor"&lt;/p&gt;
&lt;p&gt;Il reste maintenant à ajouter des données.&lt;/p&gt;
&lt;h2 id="installation-de-telegraf"&gt;Installation de Telegraf&lt;/h2&gt;
&lt;p&gt;Telegraf s'installe de la même façon que Chronograf :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ sudo aptitude install telegraf
$ sudo systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; telegraf
$ sudo systemctl start telegraf
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Telegraph est construit autour de plugins d'entrée (inputs) pour accéder aux données des mesures, et des plugins de sortie (outputs) pour aller stocker les données. Les plugins de Telegraf sont écrits en GO.&lt;/p&gt;
&lt;p&gt;Il y a toutes sortes de plugins d'entrée pour obtenir des mesures sur une quantité incroyable de systèmes (Apache, Elasticsearch, Docker, etc...). La &lt;a href="https://docs.influxdata.com/telegraf/v1.4/inputs/"&gt;documentation de Telegraf&lt;/a&gt; comporte le descriptif de chacun des plugins qui viennent avec telegraf.&lt;/p&gt;
&lt;p&gt;Il y a également toutes sortes de plugins de sortie pour stocker les données récupérées dans différents types de bases de données. Par défaut InfluxDB, mais aussi (non exhaustif) Kafka, Graylog, Elasticsearch, Datadog ou des fichiers plats.&lt;/p&gt;
&lt;p&gt;Dans la configuration par défaut de telegraf, les plugins d'entrée suivants sont activés et collectent des métriques systèmes sur la machine sur laquelle Telegraf tourne :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;cpu&lt;/li&gt;
&lt;li&gt;disk&lt;/li&gt;
&lt;li&gt;diskio&lt;/li&gt;
&lt;li&gt;kernel&lt;/li&gt;
&lt;li&gt;mem&lt;/li&gt;
&lt;li&gt;processes&lt;/li&gt;
&lt;li&gt;swap&lt;/li&gt;
&lt;li&gt;system&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Et les données sont stockées par défaut dans une base de données &lt;code&gt;telegraf&lt;/code&gt; d'InfluxDB sur l'hôte local (&lt;code&gt;localhost:8086&lt;/code&gt;) sans authentification. ça tombe bien parce que c'est notre cas, nous n'avons donc pas besoin de toucher à la configuration de Telegraf pour commencer à récolter des données et les voir dans Chronograf. La configuration de Telegraf se trouve sous &lt;code&gt;/etc/telegraf&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Telegraf construit également un dashboard système par défaut de la machine locale dans Chronograf. Vous le retrouverez sous &lt;code&gt;Host List&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="img3" src="/static/img/raspi-tick-stack/telegraf-system-dashboard.png" title="dashboard système par défaut" /&gt;&lt;/p&gt;
&lt;p&gt;Et maintenant que vous avez plein de données toutes fraiches, vous pouvez jouer à les explorer (&lt;code&gt;Data Explorer&lt;/code&gt;) et à faire vos propres tableaux de bord (&lt;code&gt;dashboards&lt;/code&gt;). Notez que la partie &lt;code&gt;Data Explorer&lt;/code&gt; est beaucoup plus limitée, je n'ai notamment pas trouvé moyen de changer le type de graphe alors que c'est enfantin dans les dashboards.&lt;/p&gt;
&lt;h2 id="installation-de-kapacitor"&gt;Installation de Kapacitor&lt;/h2&gt;
&lt;p&gt;Maintenant que nous avons des données, pourquoi ne pas en profiter pour alarmer sur dépassement de seuil ? C'est le travail de Kapacitor.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ sudo aptitude install kapacitor
$ sudo systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; kapacitor
$ sudo systemctl start kapacitor
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Vous devez ensuite "brancher" Kapacitor sur InfluxDB et Chronograf. Pour cela, dans l'interface de Chronograf, allez dans &lt;code&gt;Configuration&lt;/code&gt; et dans la colonne &lt;code&gt;Active Kapacitor&lt;/code&gt;, cliquez sur le bouton &lt;code&gt;Add Config&lt;/code&gt; de votre source de données.&lt;/p&gt;
&lt;p&gt;&lt;img alt="img4" src="/static/img/raspi-tick-stack/kapacitor-chronograf-config1.png" title="Ajout configuration Kapacitor 1/3" /&gt;&lt;/p&gt;
&lt;p&gt;Saisissez ensuite les informations de connexion à Kapacitor (Normalement les valeurs préremplies sur suffisantes) et validez.&lt;/p&gt;
&lt;p&gt;&lt;img alt="img5" src="/static/img/raspi-tick-stack/kapacitor-chronograf-config2.png" title="Ajout configuration Kapacitor 2/3" /&gt; &lt;/p&gt;
&lt;p&gt;Enfin, scrollez en bas de l'écran et ajoutez des moyens d'alerting. Ici par exemple la configuration de l'alerting par mail :&lt;/p&gt;
&lt;p&gt;&lt;img alt="img6" src="/static/img/raspi-tick-stack/kapacitor-chronograf-config3.png" title="Ajout configuration Kapacitor 3/3" /&gt;&lt;/p&gt;
&lt;p&gt;Et voilà ! Vous pouvez maintenant définir des alertes dans &lt;code&gt;Alerting&lt;/code&gt;-&amp;gt;&lt;code&gt;Alert Rules&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="img7" src="/static/img/raspi-tick-stack/kapacitor-alert1.png" title="Création d'une alerte Kapacitor 1/2" /&gt;
&lt;img alt="img8" src="/static/img/raspi-tick-stack/kapacitor-alert2.png" title="Création d'une alerte Kapacitor 2/2" /&gt;&lt;/p&gt;
&lt;h1 id="ajoutons-une-source-de-donnees"&gt;Ajoutons une source de données&lt;/h1&gt;
&lt;p&gt;Bon, on a la base, mais maintenant, on veut ajouter nos données à nous. Par exemple la température du CPU du Raspberry Pi.
On peut la lire facilement dans &lt;code&gt;/sys/class/thermal/thermal_zone0/temp&lt;/code&gt; (c'est une valeur multipliée par 1000).&lt;/p&gt;
&lt;p&gt;On va donc créer un petit programme en python qui va lire cette valeur et retourner les données en format json. On crée pour cela le fichier &lt;code&gt;/etc/telegraf/pi_temp.py&lt;/code&gt; avec le contenu suivant :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ch"&gt;#!/usr/bin/env python3&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;

&lt;span class="c1"&gt;# This gets the CPU temp&lt;/span&gt;
&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/sys/class/thermal/thermal_zone0/temp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;


&lt;span class="n"&gt;json_body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;sensor&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;cpu&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;temperature&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort_keys&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;On le rend executable et on teste :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; /etc/telegraf/
$ chmod +x pi_temp.py
$ ./pi_temp.py
&lt;span class="o"&gt;[&lt;/span&gt;
  &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;sensor&amp;quot;&lt;/span&gt;: &lt;span class="s2"&gt;&amp;quot;cpu&amp;quot;&lt;/span&gt;,
    &lt;span class="s2"&gt;&amp;quot;temperature&amp;quot;&lt;/span&gt;: 45.084
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Il n'y a plus alors qu'à utiliser le plugin &lt;code&gt;exec&lt;/code&gt; de Telegraf pour que les données soient automagiquement envoyées toutes les 10 secondes dans InfluxDB. Modifiez la section &lt;code&gt;inputs.exec&lt;/code&gt; du fichier &lt;code&gt;/etc/telegraf/telegraf.conf&lt;/code&gt; comme cela :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;# # Read metrics from one or more commands that can output to stdout
[[inputs.exec]]
  ## Commands array
  commands = [
    &amp;quot;/etc/telegraf/pi_temp.py&amp;quot;
  ]

  ## Timeout for each command to complete.
  timeout = &amp;quot;5s&amp;quot;

  ## measurement name suffix (for separating different commands)
  name_prefix = &amp;quot;temperature_&amp;quot;

  ## Data format to consume.
  ## Each data format has its own unique set of configuration options, read
  ## more about them here:
  ## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md
  data_format = &amp;quot;json&amp;quot;

  ## List of tag names to extract from top-level of JSON server response
    tag_keys = [
        &amp;quot;sensor&amp;quot;
    ]
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Et voilà, vous aurez la mesure de température du CPU du Raspberry Pi dans InfluxDB.&lt;/p&gt;
&lt;p&gt;&lt;img alt="img9" src="/static/img/raspi-tick-stack/raspi-temp.png" title="Temperature CPU du Raspberry Pi" /&gt;&lt;/p&gt;
&lt;p&gt;Amusez vous bien avec votre pile TICK et les séries temporelles !&lt;/p&gt;</summary><category term="raspi"></category><category term="raspberry"></category><category term="TICK"></category><category term="influxdb"></category><category term="time-series"></category></entry><entry><title>BreizhC@mp 2016</title><link href="https://blog.blaisot.org/breizhcmp-2016.html" rel="alternate"></link><published>2016-03-24T22:28:00+01:00</published><updated>2016-03-24T22:28:00+01:00</updated><author><name>Sébastien Blaisot</name></author><id>tag:blog.blaisot.org,2016-03-24:breizhcmp-2016.html</id><summary type="html">
        &lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
        &lt;h1&gt;Introduction&lt;/h1&gt;
          Lors du BreizhCamp 2016, il y avait une erreur d'impression de la banderole d'accueil.
          &lt;blockquote class="twitter-tweet" data-lang="fr"&gt;&lt;p lang="fr" dir="ltr"&gt;&lt;a href="https://twitter.com/breizhcamp"&gt;@breizhcamp&lt;/a&gt; nous y sommes 👍 &lt;a href="https://t.co/uHqHWQKlaR"&gt;pic.twitter.com/uHqHWQKlaR&lt;/a&gt;&lt;/p&gt;&amp;mdash; CODE 42 (@CODE_42) &lt;a href="https://twitter.com/CODE_42/status/712656324929142785"&gt;23 mars 2016&lt;/a&gt;&lt;/blockquote&gt;

         Cela s'est vite transformé en jeu concours lors de la keynote : trouver la fin de la banderole. Défi relevé, voici un tour d'horizon du Breizhcamp 2016 s'appuyant sur vos twits avec un clin d'oeil à la banderole à chaque fois.


       &lt;h1&gt;BreizhC@...rtons, les conférences qui tiennent dans des boites&lt;/h1&gt;
          &lt;blockquote class="twitter-tweet" data-lang="fr"&gt;&lt;p lang="fr" dir="ltr"&gt;Bref, le mec d&amp;#39;UPS et moi on se fait la bise maintenant (cc &lt;a href="https://twitter.com/breizhcamp"&gt;@breizhcamp&lt;/a&gt;) &lt;a href="https://t.co/sWsKDdheI1"&gt;pic.twitter.com/sWsKDdheI1&lt;/a&gt;&lt;/p&gt;&amp;mdash; Nicolas De loof (@ndeloof) &lt;a href="https://twitter.com/ndeloof/status/711248331348041728"&gt;19 mars 2016&lt;/a&gt;&lt;/blockquote&gt;

      &lt;h1&gt;BreizhC@...méra, si tu viens pas, c'est filmé&lt;/h1&gt;
          &lt;blockquote class="twitter-tweet" data-lang="fr"&gt;&lt;p lang="fr" dir="ltr"&gt;Je suis jaloux &lt;a href="https://t.co/EH4yzyTMSA"&gt;pic.twitter.com/EH4yzyTMSA&lt;/a&gt;&lt;/p&gt;&amp;mdash; Nicolas De loof (@ndeloof) &lt;a href="https://twitter.com/ndeloof/status/712637025413959680"&gt;23 mars 2016&lt;/a&gt;&lt;/blockquote&gt;

      &lt;h1&gt;BreizhC@...ses, pour y mettre le programme&lt;/h1&gt;
          &lt;blockquote class="twitter-tweet" data-lang="fr"&gt;&lt;p lang="fr" dir="ltr"&gt;Plus qu&amp;#39;à remplir les cases pour avoir un programme &lt;a href="https://twitter.com/hashtag/SelectionEnVue?src=hash"&gt;#SelectionEnVue&lt;/a&gt; &lt;a href="https://t.co/rzxRuhZBlP"&gt;pic.twitter.com/rzxRuhZBlP&lt;/a&gt;&lt;/p&gt;&amp;mdash; BreizhCamp (@breizhcamp) &lt;a href="https://twitter.com/breizhcamp/status/699743399704973312"&gt;16 février 2016&lt;/a&gt;&lt;/blockquote&gt;

      &lt;h1&gt;BreizhC@...issière, un rève de gosse&lt;/h1&gt;
          &lt;blockquote class="twitter-tweet" data-lang="fr"&gt;&lt;p lang="fr" dir="ltr"&gt;Après le choix du programme du &lt;a href="https://twitter.com/breizhcamp"&gt;@breizhcamp&lt;/a&gt; , on passe à la caisse pour scanner le programme ! &lt;a href="https://twitter.com/hashtag/IoT?src=hash"&gt;#IoT&lt;/a&gt; &lt;a href="https://t.co/Gybdat6zg6"&gt;pic.twitter.com/Gybdat6zg6&lt;/a&gt;&lt;/p&gt;&amp;mdash; Sébastien Brousse (@seb_brousse) &lt;a href="https://twitter.com/seb_brousse/status/700429329780572160"&gt;18 février 2016&lt;/a&gt;&lt;/blockquote&gt;

      &lt;h1&gt;BreizhC@...nicule, enfin presque...&lt;/h1&gt;
          &lt;blockquote class="twitter-tweet" data-lang="fr"&gt;&lt;p lang="fr" dir="ltr"&gt;Vous êtes sûr que le Breizhcamp commence bien aujourd&amp;#39;hui ? &lt;a href="https://twitter.com/hashtag/bzhcmp?src=hash"&gt;#bzhcmp&lt;/a&gt; &lt;a href="https://t.co/dtMIJBGtA9"&gt;pic.twitter.com/dtMIJBGtA9&lt;/a&gt;&lt;/p&gt;&amp;mdash; Sébastien PRUNIER (@sebprunier) &lt;a href="https://twitter.com/sebprunier/status/712582696816533504"&gt;23 mars 2016&lt;/a&gt;&lt;/blockquote&gt;

      &lt;h1&gt;BreizhC@...ca dans les couches de bébé&lt;/h1&gt;
          &lt;blockquote class="twitter-tweet" data-lang="fr"&gt;&lt;p lang="fr" dir="ltr"&gt;Les couches de bébé dans le bigdata avec &lt;a href="https://twitter.com/vcasse"&gt;@vcasse&lt;/a&gt; au &lt;a href="https://twitter.com/hashtag/BreizhCamp?src=hash"&gt;#BreizhCamp&lt;/a&gt; &lt;a href="https://t.co/Sgz3X4arbw"&gt;pic.twitter.com/Sgz3X4arbw&lt;/a&gt;&lt;/p&gt;&amp;mdash; Sebastien BLAISOT (@SebBLAISOT) &lt;a href="https://twitter.com/SebBLAISOT/status/712973483702099969"&gt;24 mars 2016&lt;/a&gt;&lt;/blockquote&gt;

      &lt;h1&gt;BreizhC@...sseroles, des talks et des bons petits plats&lt;/h1&gt;
          &lt;blockquote class="twitter-tweet" data-lang="fr"&gt;&lt;p lang="fr" dir="ltr"&gt;Merci le &lt;a href="https://twitter.com/breizhcamp"&gt;@breizhcamp&lt;/a&gt; ! On c&amp;#39;était top cette journée !! A demain &lt;a href="https://twitter.com/hashtag/bzhcmp?src=hash"&gt;#bzhcmp&lt;/a&gt; &lt;a href="https://t.co/gLDjPe94y4"&gt;pic.twitter.com/gLDjPe94y4&lt;/a&gt;&lt;/p&gt;&amp;mdash; Nicolas Pennec (@NicoPennec) &lt;a href="https://twitter.com/NicoPennec/status/713077761452154880"&gt;24 mars 2016&lt;/a&gt;&lt;/blockquote&gt;

      &lt;h1&gt;BreizhC@...deaux, des conférences et des goodies&lt;/h1&gt;
          &lt;blockquote class="twitter-tweet" data-lang="fr"&gt;&lt;p lang="fr" dir="ltr"&gt;Trop chic au &lt;a href="https://twitter.com/hashtag/BreizhCamp?src=hash"&gt;#BreizhCamp&lt;/a&gt;, on a des cadeaux! Merci &lt;a href="https://twitter.com/jfrog"&gt;@jfrog&lt;/a&gt; :) &lt;a href="https://t.co/CEjFzjfSFR"&gt;pic.twitter.com/CEjFzjfSFR&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maxime Odye (@MaxOdye) &lt;a href="https://twitter.com/MaxOdye/status/713026493312606209"&gt;24 mars 2016&lt;/a&gt;&lt;/blockquote&gt;

      &lt;h1&gt;BreizhC@...fé, ça réveille entre deux conf&lt;/h1&gt;
          &lt;blockquote class="twitter-tweet" data-lang="fr"&gt;&lt;p lang="fr" dir="ltr"&gt;Vous l&amp;#39;avez adoré, il fait son come back : le café !  sinon le thé glacé et la citronnade sont excellents &lt;a href="https://t.co/COMzqrUFiV"&gt;pic.twitter.com/COMzqrUFiV&lt;/a&gt;&lt;/p&gt;&amp;mdash; BreizhCamp (@breizhcamp) &lt;a href="https://twitter.com/breizhcamp/status/713011251123785733"&gt;24 mars 2016&lt;/a&gt;&lt;/blockquote&gt;

      &lt;h1&gt;BreizhC@...nard, mais un super canard !&lt;/h1&gt;
          &lt;blockquote class="twitter-tweet" data-lang="fr"&gt;&lt;p lang="fr" dir="ltr"&gt;Le &lt;a href="https://twitter.com/breizhcamp"&gt;@breizhcamp&lt;/a&gt;  avec en guest &lt;a href="https://twitter.com/CommitStrip"&gt;@CommitStrip&lt;/a&gt; et &lt;a href="https://twitter.com/hashtag/CanardMan?src=hash"&gt;#CanardMan&lt;/a&gt; !!! &lt;a href="https://twitter.com/hashtag/bzhcmp?src=hash"&gt;#bzhcmp&lt;/a&gt; &lt;a href="https://t.co/VCLCxNDCob"&gt;pic.twitter.com/VCLCxNDCob&lt;/a&gt;&lt;/p&gt;&amp;mdash; Nicolas Pennec (@NicoPennec) &lt;a href="https://twitter.com/NicoPennec/status/713051009505996800"&gt;24 mars 2016&lt;/a&gt;&lt;/blockquote&gt;


      &lt;h1&gt;BreizhC@...sual, l'équipe OVH en mode beaux gosses&lt;/h1&gt;
        &lt;h2&gt;Décontracté, mais chic&lt;/h2&gt;
          &lt;blockquote class="twitter-tweet" data-lang="fr"&gt;&lt;p lang="fr" dir="ltr"&gt;La Team &lt;a href="https://twitter.com/hashtag/Ovh?src=hash"&gt;#Ovh&lt;/a&gt; au &lt;a href="https://twitter.com/hashtag/BreizhCamp?src=hash"&gt;#BreizhCamp&lt;/a&gt; ! &lt;a href="https://t.co/j8G0SR4f3l"&gt;pic.twitter.com/j8G0SR4f3l&lt;/a&gt;&lt;/p&gt;&amp;mdash; Sou MOOKIEN (@Sou_OVH) &lt;a href="https://twitter.com/Sou_OVH/status/712998750055178240"&gt;24 mars 2016&lt;/a&gt;&lt;/blockquote&gt;


      &lt;h1&gt;BreizhC@...sse gueule, sur de drôles d'engins à roulettes&lt;/h1&gt;
          &lt;blockquote class="twitter-tweet" data-lang="fr"&gt;&lt;p lang="fr" dir="ltr"&gt;Au &lt;a href="https://twitter.com/breizhcamp"&gt;@BreizhCamp&lt;/a&gt; ! Venez ns rencontrer pr parler Expertise &amp;amp; tentez votre chance de remporter le gros lot &lt;a href="https://twitter.com/hashtag/BreizhCamp?src=hash"&gt;#BreizhCamp&lt;/a&gt; &lt;a href="https://t.co/fhWjY54BfE"&gt;pic.twitter.com/fhWjY54BfE&lt;/a&gt;&lt;/p&gt;&amp;mdash; SOFTEAM Cadextan (@SofteamCadextan) &lt;a href="https://twitter.com/SofteamCadextan/status/712992555437309952"&gt;24 mars 2016&lt;/a&gt;&lt;/blockquote&gt;

      &lt;h1&gt;Breizhc@...rburant, pour décompresser de la journée&lt;/h1&gt;
          &lt;blockquote class="twitter-tweet" data-lang="fr"&gt;&lt;p lang="fr" dir="ltr"&gt;Sushi/bière, Merci &lt;a href="https://twitter.com/hashtag/Breizhcamp?src=hash"&gt;#Breizhcamp&lt;/a&gt; ! cc &lt;a href="https://twitter.com/dadoonet"&gt;@dadoonet&lt;/a&gt; &lt;a href="https://twitter.com/waxzce"&gt;@waxzce&lt;/a&gt; &lt;a href="https://twitter.com/snicoll"&gt;@snicoll&lt;/a&gt; &lt;a href="https://twitter.com/sdeleuze"&gt;@sdeleuze&lt;/a&gt; &lt;a href="https://t.co/rlXbxjDPoS"&gt;pic.twitter.com/rlXbxjDPoS&lt;/a&gt;&lt;/p&gt;&amp;mdash; Laurent Doguin (@ldoguin) &lt;a href="https://twitter.com/ldoguin/status/713105252287967233"&gt;24 mars 2016&lt;/a&gt;&lt;/blockquote&gt;

      &lt;h1&gt;BreizhC@...ché, le problème d'impression&lt;/h1&gt;
          &lt;blockquote class="twitter-tweet" data-lang="fr"&gt;&lt;p lang="fr" dir="ltr"&gt;Un problème d&amp;#39;impression ? Quel problème ? &lt;a href="https://twitter.com/breizhcamp"&gt;@breizhcamp&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/BreizhCamp?src=hash"&gt;#BreizhCamp&lt;/a&gt; &lt;a href="https://t.co/V1zQYqq67g"&gt;pic.twitter.com/V1zQYqq67g&lt;/a&gt;&lt;/p&gt;&amp;mdash; David Pilato (@dadoonet) &lt;a href="https://twitter.com/dadoonet/status/712916820181786628"&gt;24 mars 2016&lt;/a&gt;&lt;/blockquote&gt;

      &lt;h1&gt;BreizhC@...amelott, la conf où c'est pas faux&lt;/h1&gt;
        &lt;h2&gt;je ne peux m'empêcher d'associer ces 2 twits&lt;/h2&gt;
          &lt;blockquote class="twitter-tweet" data-conversation="none" data-lang="fr"&gt;&lt;p lang="fr" dir="ltr"&gt;&lt;a href="https://twitter.com/SebBLAISOT"&gt;@SebBLAISOT&lt;/a&gt; &lt;a href="https://twitter.com/ndeloof"&gt;@ndeloof&lt;/a&gt; &lt;a href="https://twitter.com/breizhcamp"&gt;@breizhcamp&lt;/a&gt; Tu as aussi BreizhC@melott la conf où c&amp;#39;est pas faux ou encore BreizhC@melott la conf où on en a gros !&lt;/p&gt;&amp;mdash; Frederic Alix (@fredericalix) &lt;a href="https://twitter.com/fredericalix/status/712995682857127937"&gt;24 mars 2016&lt;/a&gt;&lt;/blockquote&gt;
        &amp;nbsp;
          &lt;blockquote class="twitter-tweet" data-lang="fr"&gt;&lt;p lang="fr" dir="ltr"&gt;Quand ils sortent le café au &lt;a href="https://twitter.com/breizhcamp"&gt;@breizhcamp&lt;/a&gt; &lt;a href="https://t.co/ZtXA3iaUNX"&gt;pic.twitter.com/ZtXA3iaUNX&lt;/a&gt;&lt;/p&gt;&amp;mdash; Guillaume A. (@GuiGuiSoft) &lt;a href="https://twitter.com/GuiGuiSoft/status/713014683213688832"&gt;24 mars 2016&lt;/a&gt;&lt;/blockquote&gt;


    </summary><category term="breizhcamp"></category><category term="BreizhC@mp"></category></entry><entry><title>Un script pour superviser l'expiration des enregistrements DNSSEC</title><link href="https://blog.blaisot.org/dnssec-sup.html" rel="alternate"></link><published>2014-06-13T13:00:00+02:00</published><updated>2014-06-13T13:00:00+02:00</updated><author><name>sblaisot</name></author><id>tag:blog.blaisot.org,2014-06-13:dnssec-sup.html</id><summary type="html">

&lt;p&gt;Dans &lt;a href="https://blog.blaisot.org/dnssec-intro.html"&gt;mon précédent article sur la mise en place de dnssec&lt;/a&gt;, je vous avais renvoyé pour la partie supervision de l'expiration des enregistrements dnssec sur un article de Stéphane Bortzmeyer expliquant comment le mettre en place sous icinga.&lt;/p&gt;
&lt;p&gt;Comme tout le monde n'a pas icinga sous la main, voici un petit script de ma composition qui vous enverra un mail lorsqu'un enregistrement RRSIG arrive à expiration (et donc que quelque chose s'est mal passé dans la resignature automatique par bind)&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c1"&gt;### CONFIGURATION DEFAULTS ###&lt;/span&gt;

&lt;span class="c1"&gt;# Warn if an RRSIG expires in less than this time period&lt;/span&gt;
&lt;span class="nv"&gt;WARN_TIME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;4 weeks&amp;quot;&lt;/span&gt;

&lt;span class="c1"&gt;# print warnings to STDOUT (true or false)&lt;/span&gt;
&lt;span class="nv"&gt;WARN_STDOUT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;

&lt;span class="c1"&gt;# Send warnings by mail (true or false)&lt;/span&gt;
&lt;span class="nv"&gt;WARN_MAIL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;

&lt;span class="c1"&gt;# Where to send mail alerts (if WARN_MAIL set to true)&lt;/span&gt;
&lt;span class="nv"&gt;SEND_WARNING_MAIL_TO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;hostmaster@example.tld&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;SEND_WARNING_MAIL_FROM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;hostmaster@example.tld&amp;quot;&lt;/span&gt;

&lt;span class="c1"&gt;# Command to get zone list. Adapt to your settings.&lt;/span&gt;
&lt;span class="nv"&gt;ZONE_LIST_COMMAND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;ls /etc/bind/keys&amp;quot;&lt;/span&gt;

&lt;span class="c1"&gt;# Signed zone file path for zone ${zone}&lt;/span&gt;
&lt;span class="c1"&gt;# Use single quotes to avoid variable expansion&lt;/span&gt;
&lt;span class="nv"&gt;ZONE_FILE_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/etc/bind/zones/db.${zone}.signed&amp;#39;&lt;/span&gt;



&lt;span class="c1"&gt;### DO NOT MODIFY ANYTHING BELOW UNLESS YOU EXACTLY KNOW WHAT YOU ARE DOING ###&lt;/span&gt;


&lt;span class="c1"&gt;# Usage function&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; usage &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;USAGE: &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;basename &lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; [-h] [-d] [-e &amp;lt;warning_time&amp;gt;] [-m] [-f &amp;lt;sender&amp;gt;] [-t &amp;lt;destination&amp;gt;] [-s] [-q]&amp;quot;&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Options:&amp;quot;&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;  -h, --help    print usage message and exit&amp;quot;&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;  -d, --debug   debug mode, show expiration date of older RRSIG record for each domain even if not in&amp;quot;&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;                warning time period (only on STDOUT)&amp;quot;&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;  -e &amp;lt;time&amp;gt;,    warn if RRSIG expires in the given time period&amp;quot;&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;  --expirein &amp;lt;time&amp;gt;&amp;quot;&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;  -m, --mail    send warning by mail&amp;quot;&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;  -f &amp;lt;sender&amp;gt;,  set warning mail sender address&amp;quot;&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;  --from &amp;lt;sender&amp;gt;&amp;quot;&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;  -t &amp;lt;dest&amp;gt;,    set warning mail destination address&amp;quot;&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;  --to &amp;lt;dest&amp;gt;&amp;quot;&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;  --nomail      do NOT send warning by mail even if enabled by default&amp;quot;&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;  -s, --stdout  show warnings on stdout&amp;quot;&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;  -q, --quiet   do NOT show warnings on stdout, even if enabled by default&amp;quot;&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;DEBUG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;

&lt;span class="c1"&gt;# Options parsing&lt;/span&gt;

&lt;span class="nv"&gt;PARSED_OPTIONS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;getopt -n &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;  -o hde:msqf:t: --long &lt;span class="s2"&gt;&amp;quot;help,debug,expirein:,mail,stdout,quiet,from:,to:,nomail,nostdout&amp;quot;&lt;/span&gt;  -- &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; -ne &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;then&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;2
  usage &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;2
  &lt;span class="nb"&gt;exit&lt;/span&gt; 1
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt; -- &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$PARSED_OPTIONS&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; true&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; in
    -h&lt;span class="p"&gt;|&lt;/span&gt;--help&lt;span class="o"&gt;)&lt;/span&gt;
      usage &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;2
      &lt;span class="nb"&gt;exit&lt;/span&gt; 1
      &lt;span class="p"&gt;;;&lt;/span&gt;
    -d&lt;span class="p"&gt;|&lt;/span&gt;--debug&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="nv"&gt;DEBUG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
      &lt;span class="nb"&gt;shift&lt;/span&gt;
      &lt;span class="p"&gt;;;&lt;/span&gt;
    -e&lt;span class="p"&gt;|&lt;/span&gt;--expirein&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; in
        &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
        *&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;WARN_TIME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt; 2&lt;span class="p"&gt;;;&lt;/span&gt;
      &lt;span class="k"&gt;esac&lt;/span&gt;
      &lt;span class="p"&gt;;;&lt;/span&gt;
    -m&lt;span class="p"&gt;|&lt;/span&gt;--mail&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="nv"&gt;WARN_MAIL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
      &lt;span class="nb"&gt;shift&lt;/span&gt;
      &lt;span class="p"&gt;;;&lt;/span&gt;
    -f&lt;span class="p"&gt;|&lt;/span&gt;--from&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; in
        &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
        *&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;SEND_WARNING_MAIL_FROM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt; 2&lt;span class="p"&gt;;;&lt;/span&gt;
      &lt;span class="k"&gt;esac&lt;/span&gt;
      &lt;span class="p"&gt;;;&lt;/span&gt;
    -t&lt;span class="p"&gt;|&lt;/span&gt;--to&lt;span class="o"&gt;)&lt;/span&gt;
       &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; in
        &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
        *&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;SEND_WARNING_MAIL_TO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt; 2&lt;span class="p"&gt;;;&lt;/span&gt;
      &lt;span class="k"&gt;esac&lt;/span&gt;
      &lt;span class="p"&gt;;;&lt;/span&gt;
    --nomail&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="nv"&gt;WARN_MAIL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
      &lt;span class="nb"&gt;shift&lt;/span&gt;
      &lt;span class="p"&gt;;;&lt;/span&gt;
    -s&lt;span class="p"&gt;|&lt;/span&gt;--stdout&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="nv"&gt;WARN_STDOUT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
      &lt;span class="nb"&gt;shift&lt;/span&gt;
      &lt;span class="p"&gt;;;&lt;/span&gt;
    -q&lt;span class="p"&gt;|&lt;/span&gt;--quiet&lt;span class="p"&gt;|&lt;/span&gt;--nostdout&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="nv"&gt;WARN_STDOUT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
      &lt;span class="nb"&gt;shift&lt;/span&gt;
      &lt;span class="p"&gt;;;&lt;/span&gt;
    --&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="nb"&gt;shift&lt;/span&gt;
      &lt;span class="nb"&gt;break&lt;/span&gt;
      &lt;span class="p"&gt;;;&lt;/span&gt;
  &lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="c1"&gt;# Warn time limit since epoch&lt;/span&gt;
&lt;span class="nv"&gt;WARN_EPOCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date --date &lt;span class="s2"&gt;&amp;quot;+&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;WARN_TIME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; +&lt;span class="s2"&gt;&amp;quot;%s&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# For each zone&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; zone in &lt;span class="k"&gt;$(&lt;/span&gt; &lt;span class="nv"&gt;$ZONE_LIST_COMMAND&lt;/span&gt; &lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

  &lt;span class="c1"&gt;# Get expiration time of next expiring RRSIG&lt;/span&gt;
  &lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;named-compilezone -q -D -f raw -o - &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;zone&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ZONE_FILE_PATH&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="s2"&gt;&amp;quot;IN RRSIG&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;awk &lt;span class="s1"&gt;&amp;#39;{ print $9 }&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;sort -n &lt;span class="p"&gt;|&lt;/span&gt;head -1&lt;span class="k"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Transform to epoch (usefull for date comparison)&lt;/span&gt;
  &lt;span class="nv"&gt;EXP_EPOCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date --date &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;6&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;4&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;12&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; +&lt;span class="s2"&gt;&amp;quot;%s&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
  &lt;span class="nv"&gt;EXP_HUMANREADABLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;LANG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;C date --date &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;6&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;4&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;12&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Warn if in expiration warning time&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;EXP_EPOCH&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; -le &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;WARN_EPOCH&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="nv"&gt;WARN_MSG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;\&lt;/span&gt;

&lt;span class="s2"&gt;DNSSEC EXPIRATION WARNING&lt;/span&gt;
&lt;span class="s2"&gt;-------------------------&lt;/span&gt;

&lt;span class="s2"&gt;Domain &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;zone&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; has an RRSIG expiring in less than &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;WARN_TIME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&lt;/span&gt;
&lt;span class="s2"&gt;Next expiration date on (&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;EXP_EPOCH&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;) &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;EXP_HUMANREADABLE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&lt;/span&gt;
&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="nv"&gt;$WARN_STDOUT&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;WARN_MSG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$WARN_MAIL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
      &lt;span class="nv"&gt;WARN_MAIL_HEADERS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;\&lt;/span&gt;
&lt;span class="s2"&gt;From: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SEND_WARNING_MAIL_FROM&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&lt;/span&gt;
&lt;span class="s2"&gt;To: &amp;lt;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SEND_WARNING_MAIL_TO&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="s2"&gt;Subject: ***DNSSEC RRSIG EXPIRATION WARNING ***&lt;/span&gt;
&lt;span class="s2"&gt;Date: &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date -R&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&lt;/span&gt;
&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
      &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;WARN_MAIL_HEADERS&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;WARN_MSG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sendmail -t -oi -f &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SEND_WARNING_MAIL_FROM&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="nv"&gt;$DEBUG&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Next Expiration of zone &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;zone&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (no warning) on (&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;EXP_EPOCH&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;) &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;EXP_HUMANREADABLE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="nb"&gt;exit&lt;/span&gt; 0
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Tout ce que vous avez à faire, c'est de déposer ce scripts dans &lt;code&gt;/etc/cron.daily&lt;/code&gt; (n'oubliez pas de le rendre exécutable) et adapter les valeurs par défaut en début de script et hop, vous recevrez un mail 3 jours avant l'expiration des enregistrements RRSIG.&lt;/p&gt;
&lt;p&gt;La variable &lt;code&gt;WARN_TIME&lt;/code&gt; contient la période de temps dans laquelle la présence de l'expiration d'un enregistrement RRSIG provoque une alarme. C'est une "date string" compréhensible par la commande date. Par exemple, 3 days provoquera une alarme si un enregistrement RRSIG arrive a expiration dans les 3 prochains jours. On peut également utiliser "Next thursday" pour les domaines dont un enregistrement RRSIG arrive a expiration avant jeudi prochain, ou bien "next month".&lt;/p&gt;
&lt;p&gt;Les variables &lt;code&gt;WARN_STDOUT&lt;/code&gt; et &lt;code&gt;WARN_MAIL&lt;/code&gt; servent respectivement à afficher les warning sur la sortie standard ou à les envoyer par mail.&lt;/p&gt;
&lt;p&gt;Les variables &lt;code&gt;SEND_WARNING_MAIL_TO&lt;/code&gt;et &lt;code&gt;SEND_WARNING_MAIL_FROM&lt;/code&gt; servent à définir respectivement le(s) destinataire(s) et l'expéditeur (d'en-tête et d'enveloppe) du mail d'alarme.&lt;/p&gt;
&lt;p&gt;La variable &lt;code&gt;ZONE_LIST_COMMAND&lt;/code&gt;indique au script comment obtenir la liste des domaines à checker. Pour mon cas, chaque domaine a ses clés dans un sous-répertoire spécifique de /etc/bind/keys dont le nom est le nom du domaine. Ainsi, je me contente de lister le contenu de /etc/bind/keys. Toute autre commande qui fournit la liste des domaines à vérifier fera l'affaire. Au pire, le cat d'un fichier texte.&lt;/p&gt;
&lt;p&gt;Enfin, la variable &lt;code&gt;ZONE_FILE_PATH&lt;/code&gt; indique le chemin du fichier de zone signé pour la zone &lt;code&gt;${zone}&lt;/code&gt;. Pensez à utiliser des simples quotes pour éviter l'expansion de la variable &lt;code&gt;${zone}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;J'ai préféré baser ce script sur le contenu des fichiers de zone signés plutôt que sur une interrogation du DNS.&lt;/p&gt;
&lt;p&gt;Vous pouvez aussi l'appeler manuellement avec les options qui vont bien :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;USAGE&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dnssec&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;monitor&lt;/span&gt; &lt;span class="o"&gt;[-&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;[-&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;[-&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;warning_time&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;]&lt;/span&gt; &lt;span class="o"&gt;[-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;[-&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;]&lt;/span&gt; &lt;span class="o"&gt;[-&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;destination&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;]&lt;/span&gt; &lt;span class="o"&gt;[-&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;[-&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;Options&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;help&lt;/span&gt;    &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="n"&gt;usage&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;exit&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;   &lt;span class="n"&gt;debug&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;expiration&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;older&lt;/span&gt; &lt;span class="n"&gt;RRSIG&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;each&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt; &lt;span class="n"&gt;even&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
                &lt;span class="n"&gt;warning&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="n"&gt;period&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;STDOUT&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;,&lt;/span&gt;    &lt;span class="n"&gt;warn&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;RRSIG&lt;/span&gt; &lt;span class="n"&gt;expires&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;given&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="n"&gt;period&lt;/span&gt;
  &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;expirein&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;mail&lt;/span&gt;    &lt;span class="n"&gt;send&lt;/span&gt; &lt;span class="n"&gt;warning&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;mail&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;,&lt;/span&gt;  &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="n"&gt;warning&lt;/span&gt; &lt;span class="n"&gt;mail&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;
  &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;,&lt;/span&gt;    &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="n"&gt;warning&lt;/span&gt; &lt;span class="n"&gt;mail&lt;/span&gt; &lt;span class="n"&gt;destination&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;
  &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;nomail&lt;/span&gt;      &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="n"&gt;NOT&lt;/span&gt; &lt;span class="n"&gt;send&lt;/span&gt; &lt;span class="n"&gt;warning&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;mail&lt;/span&gt; &lt;span class="n"&gt;even&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;enabled&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;  &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;warnings&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;quiet&lt;/span&gt;   &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="n"&gt;NOT&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;warnings&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;even&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;enabled&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Par exemple, pour afficher le résultat sur la sortie standard, ne pas envoyer de mail, alarmer s'il y a une expiration dans les 16 prochains jours, et afficher les prochaines dates d'expiration pour chaque domaine même s'il n'y a pas d'expiration dans la période indiquée :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ ./dnssec-monitor --nomail -s -e &lt;span class="s2"&gt;&amp;quot;16 days&amp;quot;&lt;/span&gt; -d
Next Expiration of zone example.tld &lt;span class="o"&gt;(&lt;/span&gt;no warning&lt;span class="o"&gt;)&lt;/span&gt; on &lt;span class="o"&gt;(&lt;/span&gt;1404131654&lt;span class="o"&gt;)&lt;/span&gt; Mon Jun &lt;span class="m"&gt;30&lt;/span&gt; 14:34:14 CEST 2014
Next Expiration of zone example2.tld &lt;span class="o"&gt;(&lt;/span&gt;no warning&lt;span class="o"&gt;)&lt;/span&gt; on &lt;span class="o"&gt;(&lt;/span&gt;1404130965&lt;span class="o"&gt;)&lt;/span&gt; Mon Jun &lt;span class="m"&gt;30&lt;/span&gt; 14:22:45 CEST 2014
Next Expiration of zone example3.tld &lt;span class="o"&gt;(&lt;/span&gt;no warning&lt;span class="o"&gt;)&lt;/span&gt; on &lt;span class="o"&gt;(&lt;/span&gt;1404133571&lt;span class="o"&gt;)&lt;/span&gt; Mon Jun &lt;span class="m"&gt;30&lt;/span&gt; 15:06:11 CEST 2014

DNSSEC EXPIRATION WARNING
-------------------------

Domain example4.tld has an RRSIG expiring in less than &lt;span class="m"&gt;16&lt;/span&gt; days
Next expiration date on &lt;span class="o"&gt;(&lt;/span&gt;1403990327&lt;span class="o"&gt;)&lt;/span&gt; Sat Jun &lt;span class="m"&gt;28&lt;/span&gt; 23:18:47 CEST 2014
&lt;/pre&gt;&lt;/div&gt;</summary><category term="linux"></category><category term="dnssec"></category><category term="supervision"></category></entry><entry><title>Introduction à DNSSEC</title><link href="https://blog.blaisot.org/dnssec-intro.html" rel="alternate"></link><published>2014-05-30T18:00:00+02:00</published><updated>2014-05-30T18:00:00+02:00</updated><author><name>sblaisot</name></author><id>tag:blog.blaisot.org,2014-05-30:dnssec-intro.html</id><summary type="html">&lt;h1 id="introduction"&gt;Introduction&lt;/h1&gt;
&lt;p&gt;
Le système DNS permet de faire l'association entre un nom humainement comprésensible et une adresse IP (et vice-versa). Le fonctionnement du DNS a été défini et implémenté dans les années 80, à une époque où la sécurité sur internet n'était pas encore une préoccupation.&lt;/p&gt;
&lt;p&gt;De ce fait, par design, le système DNS, par son protocole de base, est vulnérable, en ce sens qu'il est basé sur la confiance. Nos ordinateurs posent des questions au serveur DNS, reçoivent des réponses, mais n'ont pas les moyens de s'assurer que la réponse qu'ils reçoivent est légitime. l'extension DNSSEC, définie dès 1999 par la &lt;a href="http://www.ietf.org/rfc/rfc2535.txt"&gt;RFC 2535&lt;/a&gt; et complété par les &lt;a href="http://www.ietf.org/rfc/rfc4033.txt"&gt;RFC 4033&lt;/a&gt;, &lt;a href="http://www.ietf.org/rfc/rfc4034.txt"&gt;RFC 4034&lt;/a&gt; et &lt;a href="http://www.ietf.org/rfc/rfc4035.txt"&gt;RFC 4035&lt;/a&gt;, permet de combler ce manque en introduisant une chaine de signature numérique jusqu'à la signature des enregistrements d'une zone DNS par son propriétaire, chaine de singature qui pourra être vérifiée par quiconque aura besoin de l'information.&lt;/p&gt;
&lt;p&gt;Nous allons donc voir comment s'assurer que notre resolveur vérifie les signatures DNSSEC et si non, comment le mettre en place, puis comment signer sa zone dns et la gérer.&lt;/p&gt;


&lt;p&gt;Cet article s'appuie sur bind 9.9.5 sous ubuntu LTS 14.04.&lt;/p&gt;
&lt;div class="toc"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#introduction"&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#sassurer-que-son-serveur-dns-verifie-les-signatures-dnssec"&gt;S'assurer que son serveur DNS vérifie les signatures DNSSEC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#configuration-dun-bind-recursif-pour-verifier-les-signatures-dns"&gt;Configuration d'un bind récursif pour vérifier les signatures DNS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#mise-en-place-dune-zone-signee"&gt;Mise en place d'une zone signée&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#prerequis"&gt;Prérequis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#une-zone-basique-pour-commencer"&gt;Une zone basique pour commencer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#generation-des-cles"&gt;Génération des clés&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#configuration-de-bind-pour-signer-la-zone"&gt;Configuration de Bind pour signer la zone&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#utiliser-nsec3-plutot-que-nsec"&gt;Utiliser NSEC3 plutôt que NSEC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#publication-dans-la-zone-parente"&gt;Publication dans la zone parente&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#verifier-le-bon-fonctionnement"&gt;Vérifier le bon fonctionnement&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#maintenance-dune-zone-signee"&gt;Maintenance d'une zone signée&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#modification-du-contenu-de-la-zone"&gt;Modification du contenu de la zone&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#supervision"&gt;Supervision&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#rotation-de-cle"&gt;Rotation de clé&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#references"&gt;Références&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h1 id="sassurer-que-son-serveur-dns-verifie-les-signatures-dnssec"&gt;S'assurer que son serveur DNS vérifie les signatures DNSSEC&lt;/h1&gt;
&lt;p&gt;La première des choses consiste à vérifier que le serveur DNS que votre poste utilise vérifie bien les signatures DNSSEC.&lt;/p&gt;
&lt;p&gt;Nous allons donc effectuer une requête positive et une requête négative pour s'assurer à la fois que les informations correctement signées sont vérifiées comme tel et que les informations mal signées conduisent à un échec (SERVFAIL), échec qui ne se présente pas quand on désactive la vérification de signature DNSSEC :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ dig sigok.verteiltesysteme.net

&lt;span class="p"&gt;;&lt;/span&gt; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.9.5-3-Ubuntu &amp;lt;&amp;lt;&amp;gt;&amp;gt; sigok.verteiltesysteme.net
&lt;span class="p"&gt;;;&lt;/span&gt; global options: +cmd
&lt;span class="p"&gt;;;&lt;/span&gt; Got answer:
&lt;span class="p"&gt;;;&lt;/span&gt; -&amp;gt;&amp;gt;HEADER&lt;span class="s"&gt;&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 57950&lt;/span&gt;
&lt;span class="s"&gt;;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 5&lt;/span&gt;

&lt;span class="s"&gt;[...]&lt;/span&gt;

&lt;span class="s"&gt;$ dig sigfail.verteiltesysteme.net&lt;/span&gt;

&lt;span class="s"&gt;; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.9.5-3-Ubuntu &amp;lt;&amp;lt;&amp;gt;&amp;gt; sigfail.verteiltesysteme.net&lt;/span&gt;
&lt;span class="s"&gt;;; global options: +cmd&lt;/span&gt;
&lt;span class="s"&gt;;; Got answer:&lt;/span&gt;
&lt;span class="s"&gt;;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode&lt;/span&gt;: QUERY, status: SERVFAIL, id: 8675
&lt;span class="p"&gt;;;&lt;/span&gt; flags: qr rd ra&lt;span class="p"&gt;;&lt;/span&gt; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

&lt;span class="o"&gt;[&lt;/span&gt;...&lt;span class="o"&gt;]&lt;/span&gt;

$ dig +cd sigfail.verteiltesysteme.net

&lt;span class="p"&gt;;&lt;/span&gt; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.9.5-3-Ubuntu &amp;lt;&amp;lt;&amp;gt;&amp;gt; +cd sigfail.verteiltesysteme.net
&lt;span class="p"&gt;;;&lt;/span&gt; global options: +cmd
&lt;span class="p"&gt;;;&lt;/span&gt; Got answer:
&lt;span class="p"&gt;;;&lt;/span&gt; -&amp;gt;&amp;gt;HEADER&lt;span class="s"&gt;&amp;lt;&amp;lt;- opco&lt;/span&gt;de: QUERY, status: NOERROR, id: 55863
&lt;span class="p"&gt;;;&lt;/span&gt; flags: qr rd ra cd&lt;span class="p"&gt;;&lt;/span&gt; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 5

&lt;span class="p"&gt;;;&lt;/span&gt; OPT PSEUDOSECTION:
&lt;span class="p"&gt;;&lt;/span&gt; EDNS: version: 0, flags:&lt;span class="p"&gt;;&lt;/span&gt; udp: 4096
&lt;span class="p"&gt;;;&lt;/span&gt; QUESTION SECTION:
&lt;span class="p"&gt;;&lt;/span&gt;sigfail.verteiltesysteme.net.  IN  A

&lt;span class="p"&gt;;;&lt;/span&gt; ANSWER SECTION:
sigfail.verteiltesysteme.net. &lt;span class="m"&gt;60&lt;/span&gt; IN A   134.91.78.139

&lt;span class="o"&gt;[&lt;/span&gt;...&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Dans le premier cas de figure, avec une signature correcte, le flag AD (Authenticated Data) dans la réponse indique qu'une signature dnssec a été vérifiée correctement.&lt;/p&gt;
&lt;p&gt;Dans le second cas, le serveur DNS a refusé de nous répondre (SERVFAIL) parce que la signature est incorrecte.&lt;/p&gt;
&lt;p&gt;Enfin, dans le troisième cas, nous avons demandé à notre résolveur de ne pas vérifier les signatures DNSSEC (CD = Check Disabled) et nous obtenons bien une réponse, c'est donc bien une erreur DNSSEC qui provoque le SERVFAIL dans le deuxième cas de figure. La présence du flag CD dans la réponse indique que la vérification DNSSEC a été désactivée.&lt;/p&gt;
&lt;p&gt;Mode livre dont vous êtes le héro :&lt;/p&gt;
&lt;p&gt;Si vous obtenez le même résultat, bravo, vous utilisez un résolveur DNS qui vérifie les signatures DNSSEC, vous pouvez passer directement à la mise en place d'une zone signée.&lt;/p&gt;
&lt;p&gt;Dans le cas contraire, vous aurez une réponse à la deuxième requête, cela signifie que votre résolveur ne vérifie pas les signatures DNSSEC. Passez au chapitre suivant qui vous expliquera comment configurer un bind récursif pour vérifier les signatures DNSSEC.&lt;/p&gt;
&lt;h1 id="configuration-dun-bind-recursif-pour-verifier-les-signatures-dns"&gt;Configuration d'un bind récursif pour vérifier les signatures DNS&lt;/h1&gt;
&lt;p&gt;En supposant que vous ayez déjà un bind récursif pour la résolution de nom, activer la validation DNSSEC est trivial.&lt;/p&gt;
&lt;p&gt;Il suffit de s'assurer que la clé de la root zone '.' est bien incluse dans votre distribution de bind (généralement dans &lt;code&gt;/etc/bind/bind.keys&lt;/code&gt;) et d'ajouter dans le fichier named.conf (&lt;code&gt;/etc/bind/named.conf.options&lt;/code&gt; sous ubuntu) les 2 directives suivantes :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;        dnssec-enable yes;
        dnssec-validation auto;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Une relance de bind est nécessaire pour la prise en compte de ces directives :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ service bind9 restart
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Tester comme indiqué au chapitre précédent et voilà !&lt;/p&gt;
&lt;p&gt;Il est à noter que la plupart des relais DNS des box de connexion à internet (et des serveurs DNS de nos FAI) ne permettent pas la validation dnssec c'est pourquoi il est plus sûr de disposer de son propre caching-recursive-name-server plutôt que de s'appuyer sur sa box.&lt;/p&gt;
&lt;p&gt;Si vous n'utilisez pas bind mais Unbound ou un DNS microsoft, vous trouverez des éléments de configuration dans &lt;a href="http://www.surf.nl/binaries/content/assets/surf/en/knowledgebase/2012/rapport_Deploying_DNSSEC_v20.pdf"&gt;ce document&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="mise-en-place-dune-zone-signee"&gt;Mise en place d'une zone signée&lt;/h1&gt;
&lt;h2 id="prerequis"&gt;Prérequis&lt;/h2&gt;
&lt;p&gt;Pour héberger une zone DNS signée, il vous faut :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Un nom de domaine utilisant un TLD gérant DNSSEC. Cela peut se vérifier en utilisant la commande &lt;code&gt;dig ds tld&lt;/code&gt; (par exemple &lt;code&gt;dig ds com&lt;/code&gt; pour le TLD .com) qui rendra des enregistrements DS si tld gère dnssec.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Un serveur DNS, qui sait gérer des zones signées. Nous utiliserons ici bind. Depuis sa version 9.9, bind sait gérer seul tout le cycle de signature. C'est la méthode la plus simple et la moins risquée, c'est donc celle que nous utiliserons. Ainsi, nous n'aurons pas à nous préoccuper de l'expiration des enregistrements signés, à penser à signer la zone à chaque modification, etc...&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Un registrar qui vous permet de publier les enregistrements DS. Vérifiez le avant de commencer, si votre registrar ne gère pas dnssec, vous ne pourrez pas aller jusqu'au bout de la mise en place de la chaine de confiance.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="une-zone-basique-pour-commencer"&gt;Une zone basique pour commencer&lt;/h2&gt;
&lt;p&gt;Supposons que votre dns héberge déjà une zone. Pour l'exemple de cet article, nous partirons d'une zone basique &lt;code&gt;example.tld&lt;/code&gt; avec une entrée &lt;code&gt;test.example.tld&lt;/code&gt; dont l'adresse IPv4 est &lt;code&gt;1.2.3.4&lt;/code&gt;. Evidemment, le reste ne fonctionnera que s'il s'agit d'un vrai nom de domaine enregistré et connu sur internet.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;$&lt;/span&gt;&lt;span class="nv"&gt;TTL&lt;/span&gt;&lt;span class="x"&gt; 86400&lt;/span&gt;
&lt;span class="x"&gt;@       IN      SOA     ns1.example.tld. hostmaster.example.tld. (&lt;/span&gt;
&lt;span class="x"&gt;                        2014052901      ; serial number of this zone file&lt;/span&gt;
&lt;span class="x"&gt;                        8H              ; slave refresh (1 day)&lt;/span&gt;
&lt;span class="x"&gt;                        30M             ; slave retry time in case of a problem (2 hours)&lt;/span&gt;
&lt;span class="x"&gt;                        4W              ; slave expiration time (4 weeks)&lt;/span&gt;
&lt;span class="x"&gt;                        1H )            ; minimum caching time in case of failed lookups (1 hour)&lt;/span&gt;

&lt;span class="x"&gt;        IN      NS      ns1.example.tld.&lt;/span&gt;
&lt;span class="x"&gt;test    IN  A   1.2.3.4&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Définie dans la configuration de bind de la façon suivante :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;zone &amp;quot;example.tld&amp;quot; {
    type master;
    file &amp;quot;/etc/bind/db.example.tld&amp;quot;;
};
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Nous pouvons tester que l'entrée test.example.tld fonctionne bien :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nt"&gt;root&lt;/span&gt;&lt;span class="k"&gt;@vm-xubuntu&lt;/span&gt;&lt;span class="o"&gt;:/&lt;/span&gt;&lt;span class="nt"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;bind&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nt"&gt;dig&lt;/span&gt; &lt;span class="k"&gt;@serveur_dns&lt;/span&gt; &lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="nc"&gt;.example.tld&lt;/span&gt;

&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;DiG&lt;/span&gt; &lt;span class="nt"&gt;9&lt;/span&gt;&lt;span class="nc"&gt;.9.5-3-Ubuntu&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;@serveur_dns&lt;/span&gt; &lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="nc"&gt;.example.tld&lt;/span&gt;
&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;2&lt;/span&gt; &lt;span class="nt"&gt;servers&lt;/span&gt; &lt;span class="nt"&gt;found&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="nt"&gt;global&lt;/span&gt; &lt;span class="nt"&gt;options&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nt"&gt;cmd&lt;/span&gt;
&lt;span class="o"&gt;;;&lt;/span&gt; &lt;span class="nt"&gt;Got&lt;/span&gt; &lt;span class="nt"&gt;answer&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;;;&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;HEADER&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;-&lt;/span&gt; &lt;span class="nt"&gt;opcode&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;QUERY&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;status&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;NOERROR&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;21659&lt;/span&gt;
&lt;span class="o"&gt;;;&lt;/span&gt; &lt;span class="nt"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;qr&lt;/span&gt; &lt;span class="nt"&gt;aa&lt;/span&gt; &lt;span class="nt"&gt;rd&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="nt"&gt;QUERY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;ANSWER&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;AUTHORITY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;ADDITIONAL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;;;&lt;/span&gt; &lt;span class="nt"&gt;WARNING&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;recursion&lt;/span&gt; &lt;span class="nt"&gt;requested&lt;/span&gt; &lt;span class="nt"&gt;but&lt;/span&gt; &lt;span class="nt"&gt;not&lt;/span&gt; &lt;span class="nt"&gt;available&lt;/span&gt;

&lt;span class="o"&gt;;;&lt;/span&gt; &lt;span class="nt"&gt;OPT&lt;/span&gt; &lt;span class="nt"&gt;PSEUDOSECTION&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="nt"&gt;EDNS&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;:;&lt;/span&gt; &lt;span class="nt"&gt;udp&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;4096&lt;/span&gt;
&lt;span class="o"&gt;;;&lt;/span&gt; &lt;span class="nt"&gt;QUESTION&lt;/span&gt; &lt;span class="nt"&gt;SECTION&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;;&lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="nc"&gt;.example.tld&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;      &lt;span class="nt"&gt;IN&lt;/span&gt;  &lt;span class="nt"&gt;A&lt;/span&gt;

&lt;span class="o"&gt;;;&lt;/span&gt; &lt;span class="nt"&gt;ANSWER&lt;/span&gt; &lt;span class="nt"&gt;SECTION&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="nc"&gt;.example.tld&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;   &lt;span class="nt"&gt;30&lt;/span&gt;  &lt;span class="nt"&gt;IN&lt;/span&gt;  &lt;span class="nt"&gt;A&lt;/span&gt;   &lt;span class="nt"&gt;1&lt;/span&gt;&lt;span class="nc"&gt;.2.3.4&lt;/span&gt;

&lt;span class="o"&gt;;;&lt;/span&gt; &lt;span class="nt"&gt;AUTHORITY&lt;/span&gt; &lt;span class="nt"&gt;SECTION&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="nt"&gt;example&lt;/span&gt;&lt;span class="nc"&gt;.tld&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;        &lt;span class="nt"&gt;30&lt;/span&gt;  &lt;span class="nt"&gt;IN&lt;/span&gt;  &lt;span class="nt"&gt;NS&lt;/span&gt;  &lt;span class="nt"&gt;ns1&lt;/span&gt;&lt;span class="nc"&gt;.example.tld&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;;;&lt;/span&gt; &lt;span class="nt"&gt;Query&lt;/span&gt; &lt;span class="nt"&gt;time&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;32&lt;/span&gt; &lt;span class="nt"&gt;msec&lt;/span&gt;
&lt;span class="o"&gt;;;&lt;/span&gt; &lt;span class="nt"&gt;SERVER&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;xxxxx&lt;/span&gt;
&lt;span class="o"&gt;;;&lt;/span&gt; &lt;span class="nt"&gt;WHEN&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;Thu&lt;/span&gt; &lt;span class="nt"&gt;May&lt;/span&gt; &lt;span class="nt"&gt;29&lt;/span&gt; &lt;span class="nt"&gt;22&lt;/span&gt;&lt;span class="nd"&gt;:32:34&lt;/span&gt; &lt;span class="nt"&gt;CEST&lt;/span&gt; &lt;span class="nt"&gt;2014&lt;/span&gt;
&lt;span class="o"&gt;;;&lt;/span&gt; &lt;span class="nt"&gt;MSG&lt;/span&gt; &lt;span class="nt"&gt;SIZE&lt;/span&gt;  &lt;span class="nt"&gt;rcvd&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;98&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Bien, maintenant que nous avons une zone qui fonctionne, nous allons pouvoir la signer.&lt;/p&gt;
&lt;h2 id="generation-des-cles"&gt;Génération des clés&lt;/h2&gt;
&lt;p&gt;Il vous faudra 2 clés, l'une dite KSK (Key Signing Key), l'autre appelée ZSK (Zone Signing Key). La première sert à signer la seconde, la seconde sert à signer les enregistrements de la zone.&lt;/p&gt;
&lt;p&gt;Si vous avez plusieurs zones, vous aurez besoin d'une KSK, et d'une ZSK par zone à minima.&lt;/p&gt;
&lt;p&gt;Commençons par créer un répertoire où nous stockerons les clés&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ mkdir -p /etc/bind/keys
$ chgrp &lt;span class="nb"&gt;bind&lt;/span&gt; /etc/bind/keys
$ chmod u+rwx,g+srx,o-rwx /etc/bind/keys
$ &lt;span class="nb"&gt;cd&lt;/span&gt; /etc/bind/keys
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Les permissions utilisées permettent de s'assurer que bind pourra bien lire les clés.&lt;/p&gt;
&lt;p&gt;Créons la KSK :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ dnssec-keygen -a RSASHA256 -3 -f KSK -b &lt;span class="m"&gt;4096&lt;/span&gt; example.tld
Generating key pair.....................................................................................++ ...............................++ 
Kexample.tld.+008+17107
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;La génération de la clé peut être particulièrement longue si votre machine n'a pas assez d'entropie. Si tel est le cas, générez de l'entropie (accès disques, frappes au clavier, ou installation du démon haveged)&lt;/p&gt;
&lt;p&gt;Ensuite, générons une ZSK :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ dnssec-keygen -a RSASHA256 -3 -b &lt;span class="m"&gt;2048&lt;/span&gt; example.tld
Generating key pair.......+++ .......+++ 
Kexample.tld.+008+25266
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;On utilise une taille de clé de 2048 bits minimum car en dessous, &lt;s&gt;nous ne pourrons pas utiliser NSEC3 et serons limité à NSEC&lt;/s&gt; c'est moins bien. (on me signale dans l'oreillette&lt;sup id="fnref:bortzmeyer"&gt;&lt;a class="footnote-ref" href="#fn:bortzmeyer" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt; que NSEC3 fonctionne aussi avec des clés de 1024 bits).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ ls
Kexample.tld.+008+17107.key       Kexample.tld.+008+25266.key
Kexample.tld.+008+17107.private   Kexample.tld.+008+63666.private
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Nos deux clés sont créées, la KSK porte la référence (key ID) 17107 et la ZSK porte la référence 25266. Si vous ne savez plus quelle est la clé KSK de la clé ZSK, regardez le contenu du fichier .key, c'est indiqué dedans !&lt;/p&gt;
&lt;h2 id="configuration-de-bind-pour-signer-la-zone"&gt;Configuration de Bind pour signer la zone&lt;/h2&gt;
&lt;p&gt;Ensuite, il faut configurer bind  (la partie options dans &lt;code&gt;/etc/bind/named.conf.options&lt;/code&gt; et la partie concernant la zone dans &lt;code&gt;/etc/bind/named.conf.local&lt;/code&gt;) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;options {
    directory &amp;quot;/etc/bind&amp;quot;;
    key-directory &amp;quot;/etc/bind/keys&amp;quot;;
    recursion no;
    dnssec-enable yes;
};

zone &amp;quot;example.tld&amp;quot; in {
    inline-signing yes;
    auto-dnssec maintain;
    update-policy local;
    type master;
    file &amp;quot;dnssec.fr&amp;quot;;
    ...
}
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;La configuration proposée ici est la plus simple : bind se charge de tout tout seul, nous n'avons qu'à maintenir un fichier de zone non signé.&lt;/p&gt;
&lt;p&gt;La directive key-directory permet d'indiquer à bind où il doit aller chercher les clés. Cette directive peut être mise dans la section zone. C'est particulièrement utile si on utilise un répertoire différent pour stocker les clés de chaque domain.&lt;/p&gt;
&lt;p&gt;Il faut recharger bind pour prise en compte de ces modifications&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ rndc reload
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;On teste ensuite que bind renvoit bien des enregistrements signées&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ dig +dnssec test.example.tld

&lt;span class="p"&gt;;&lt;/span&gt; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.9.5-3-Ubuntu &amp;lt;&amp;lt;&amp;gt;&amp;gt; +dnssec test.example.tld
&lt;span class="p"&gt;;;&lt;/span&gt; global options: +cmd
&lt;span class="p"&gt;;;&lt;/span&gt; Got answer:
&lt;span class="p"&gt;;;&lt;/span&gt; -&amp;gt;&amp;gt;HEADER&lt;span class="s"&gt;&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 42791&lt;/span&gt;
&lt;span class="s"&gt;;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 2, ADDITIONAL: 1&lt;/span&gt;

&lt;span class="s"&gt;;; OPT PSEUDOSECTION:&lt;/span&gt;
&lt;span class="s"&gt;; EDNS: version: 0, flags: do; udp: 4096&lt;/span&gt;
&lt;span class="s"&gt;;; QUESTION SECTION:&lt;/span&gt;
&lt;span class="s"&gt;;test.example.tld.      IN  A&lt;/span&gt;

&lt;span class="s"&gt;;; ANSWER SECTION:&lt;/span&gt;
&lt;span class="s"&gt;test.example.tld.   30  IN  A   1.2.3.4&lt;/span&gt;
&lt;span class="s"&gt;test.example.tld.   30  IN  RRSIG   A 8 3 30 20140628235217 20140529231424 16140 example.tld. M+tIdL9wvT3s0rmvVYk8Rpe/+mDPeow75KQ3cMWi8THuP/yD+nRj01hU HZZzzCF4asrq+VRhwGE1rjLxdR2FPs9X7qF6IeCFrVNo2op&lt;/span&gt;xkSSsNxoq KJTGA60dbudJOShIlqvllgu6SNaes2WiUaD7s4O71UckAnG0nbVeT8Nw mEtQ2aJ6BvUONOWVAwwMNhhI8oPfZR5fVu79conWTTn/++8Y4EFD5P0F ozfdVszrrDM2tBsvv7DtX9arGqsXt0COlOz0DU8LTWJ8OVXTjku5Aetf HPpkHzhJcjX7+3CeOPfc16bNWbn2d2fs9pGj1Y9z4jNvewnnIwimcYbn &lt;span class="nv"&gt;0lBbkA&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;

&lt;span class="p"&gt;;;&lt;/span&gt; AUTHORITY SECTION:
example.tld.        &lt;span class="m"&gt;30&lt;/span&gt;  IN  NS  ns1.example.tld.
example.tld         &lt;span class="m"&gt;30&lt;/span&gt;  IN  RRSIG   NS &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt; &lt;span class="m"&gt;20140628235217&lt;/span&gt; &lt;span class="m"&gt;20140529231424&lt;/span&gt; &lt;span class="m"&gt;16140&lt;/span&gt; example.tld. K+Gi5ETPhM0pwmf4FyuL2ADaRJvkdteU0FWnrh+HLZl7mrynA4mxk6xQ IxiX3DGLpNatSax+3UzVL8itBuNzuASRXblo07dcZ88b/lJTN0XBSzcR Erjz57VYwh06W57LuiWi/YdvYO74COWGWfStmOvQ84x0wSs0VGDJnLgS Ly67lCBrLPf48AK2bQUUMvgDWhpHMr1kjgAYZZb+m/lLDMpHPU6xbAns xmkwySBQhLnNWxy9u6gzdFzn0zW5yQ/lzfoX1r5bbC6vMjaL0RMUE7Pa jeseofK021PmWB4xJM0c/Bx60OBher5bwceC9Zkr7xQhhqcKR60jlVJJ &lt;span class="nv"&gt;Q7ivRA&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;

&lt;span class="p"&gt;;;&lt;/span&gt; Query time: &lt;span class="m"&gt;6&lt;/span&gt; msec
&lt;span class="p"&gt;;;&lt;/span&gt; SERVER: 127.0.0.1#53&lt;span class="o"&gt;(&lt;/span&gt;127.0.0.1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;;;&lt;/span&gt; WHEN: Fri May &lt;span class="m"&gt;30&lt;/span&gt; 02:18:36 CEST 2014
&lt;span class="p"&gt;;;&lt;/span&gt; MSG SIZE  rcvd: 700

...
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Nous voyons bien ici les enregistrements RRSIG, bind fait bien son travail de signature.&lt;/p&gt;
&lt;p&gt;Bind a d'ailleurs créé un nouveau fichier de zone suffixé par .signed qui contient la version signée et qui peut être lu avec la commande :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ named-compilezone -D -f raw -o - example.tld db.example.tld.signed
&lt;/pre&gt;&lt;/div&gt;


&lt;h2 id="utiliser-nsec3-plutot-que-nsec"&gt;Utiliser NSEC3 plutôt que NSEC&lt;/h2&gt;
&lt;p&gt;Pour l'instant, notre zone est signée en utilisant NSEC (par défaut). Nous pouvons le vérifier par la présence d'engistrements de type NSEC retournés par la commande précédente&lt;/p&gt;
&lt;p&gt;Pour utiliser NSEC3, nous devons procurer à bind le sel à utiliser. Commençons par générer le sel :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ dd &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/random &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; md5sum &lt;span class="p"&gt;|&lt;/span&gt; cut -c1-8
10+0 enregistrements lus
10+0 enregistrements écrits
&lt;span class="m"&gt;10&lt;/span&gt; octets &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt; B&lt;span class="o"&gt;)&lt;/span&gt; copiés, 0,00278809 s, 3,6 kB/s
49d135ce
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Nous allons donc utiliser le sel &lt;code&gt;49d135ce&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ rndc signing -nsec3param &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; 49d135ce example.tld
request queued
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;et voilà. Nous avons désormais des enregistrements NSEC3 dans le fichier de zone.&lt;/p&gt;
&lt;h2 id="publication-dans-la-zone-parente"&gt;Publication dans la zone parente&lt;/h2&gt;
&lt;p&gt;Pour que la chaine de signature DNSSEC soit complète, il reste à publier l'enregistrement DS (condensat de la KSK) au niveau du TLD. Ces engegistrements seront eux-même signés par la clé du TLD.&lt;/p&gt;
&lt;p&gt;La première des choses consiste à générer ces enregistrements DS à partir de la KSK :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ dnssec-dsfromkey Kexample.tld.+008+17107.key
example.tld. IN DS &lt;span class="m"&gt;17107&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; E89E85FFD0377CBC50BBD36F3275B460FD6B5A75
example.tld. IN DS &lt;span class="m"&gt;17107&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; 08E46F22CE866971DC41A4A770A35E6EF3FA659EBB9FEC5DA81B716BD68F7B82
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Maintenant que nous avons ces 2 enregistrements, il nous faut les déclarer.&lt;/p&gt;
&lt;p&gt;L'interface de votre registrar devrait vous permettre de déclarer ces enregistrements. Si tel n'est pas le cas, il ne vous reste plus qu'à changer de registrar.&lt;/p&gt;
&lt;p&gt;S'il ne vous permet pas de copier/coller la ligne entière mais présente des champs à remplir, voici les informations contenues dans ces enregistrements :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;17107 : Il s'agit de la Key ID (identifiant de clé)&lt;/li&gt;
&lt;li&gt;8 : ceci est l'algorithme de chiffrement. Ici 8 = RSHSHA256. On rencontre aussi parfois 5 = RSASHA1&lt;/li&gt;
&lt;li&gt;1 ou 2 : le type de condensat : 1 = SHA1, 2 = SHA256&lt;/li&gt;
&lt;li&gt;la longue suite hexadécimale : il s'agit du condensat de la clé&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="verifier-le-bon-fonctionnement"&gt;Vérifier le bon fonctionnement&lt;/h2&gt;
&lt;p&gt;Une fois tout ceci effectué, cela devrait normalement être fonctionnel. Vous pouvez le vérifier sur le &lt;a href="http://dnssec-debugger.verisignlabs.com/"&gt;debugger DNSSEC verisign&lt;/a&gt;.
Si vous avez des points verts partout, bravo, votre domaine est maintenant signé par DNSSEC.&lt;/p&gt;
&lt;p&gt;L'utilitaire &lt;a href="http://www.zonecheck.fr/demo/"&gt;ZoneCheck&lt;/a&gt; dispose également d'une option pour tester la configuration DNSSEC d'un domaine (entre autres choses)&lt;/p&gt;
&lt;p&gt;L'interrogation d'un autre serveur dns récursif prenant en charge la vérification DNSSEC présentera le flag AD (Authenticated Data), votre domaine est maintenant signé grâce à DNSSEC.&lt;/p&gt;
&lt;h1 id="maintenance-dune-zone-signee"&gt;Maintenance d'une zone signée&lt;/h1&gt;
&lt;h2 id="modification-du-contenu-de-la-zone"&gt;Modification du contenu de la zone&lt;/h2&gt;
&lt;p&gt;Lorsque vous voulez désormais modifier une zone signée automatiquement par bind, il vous faut freezer la zone, faire vos modifications, puis libérer la zone, ce qui provoquera un rechargement et une resignature par bind. Cela ne vous dispense évidemment pas de mettre à jour le serial de la zone.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ rndc freeze example.tld

&lt;span class="o"&gt;[&lt;/span&gt;...Éditer le fichier de zone...&lt;span class="o"&gt;]&lt;/span&gt;

$ rndc thaw example.tld
A zone reload and thaw was started.
Check the logs to see the result.
&lt;/pre&gt;&lt;/div&gt;


&lt;h2 id="supervision"&gt;Supervision&lt;/h2&gt;
&lt;p&gt;Il est important de superviser que les opérations de resignature régulières des zones fonctionnent correctement, car en cas d'expiration des enregistrements RRSIG, votre domaine ne serait plus joignable.&lt;/p&gt;
&lt;p&gt;Je vous renvoie pour cela à &lt;a href="http://www.bortzmeyer.org/monitor-dnssec.html"&gt;cet excellent article&lt;/a&gt; de stéphane Bortzmeyer qui détaille très clairement comment il a mis en place la supervision de l'expiration des enregistrements RRSIG à l'aide d'un script perl et d'icinga.&lt;/p&gt;
&lt;h2 id="rotation-de-cle"&gt;Rotation de clé&lt;/h2&gt;
&lt;p&gt;Les clés doivent être remplacées régulièrement. On parle de key-rollover. Plus souvent pour la ZSK, qui est plus petite et surtout qui n'est pas publiée dans les DNS de niveau supérieur (donc plus facile à remplacer).&lt;/p&gt;
&lt;p&gt;Je vous conseille un remplacement des ZSK tous les 6 mois et un remplacement de la KSK tous les 2 ans. Ceci est bien entendu à ajuster en fonction de la criticité de votre domaine (et du temps dont vous disposez).&lt;/p&gt;
&lt;p&gt;Une rotation de clé est toujours une opération minutieuse qu'il vaut mieux avoir répété avant sur un domaine de faible importance car les risques de se prendre les pieds dans le tapis sont grands, et cela pourrait rendre votre domaine inutilisable pendant quelques temps.&lt;/p&gt;
&lt;p&gt;Pour la rotation de la ZSK, on commence par créer une nouvelle ZSK, puis on indique que la clé doit être retirée dans 2 jours et supprimée dans 6 jours (à ajuster en fonction des TTL) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ &lt;span class="c1"&gt;# Génération de la nouvelle ZSK&lt;/span&gt;
$ dnssec-keygen -a RSASHA256 -b &lt;span class="m"&gt;2048&lt;/span&gt; example.tld
Generating key pair...............................................+++ ....................................................................................................................+++ 
Kexample.tld.+008+21999

$ &lt;span class="c1"&gt;# On indique que la clé doit être retirée dans 2 jours&lt;/span&gt;
$ dnssec-settime -I +2d Kexample.tld.+008+25266.key
dnssec-settime: warning: Permissions on the file ./Kexample.tld.+008+25266.private have changed from &lt;span class="m"&gt;0640&lt;/span&gt; to &lt;span class="m"&gt;0600&lt;/span&gt; as a result of this operation.
./Kexample.tld.+008+25266.key
./Kexample.tld.+008+25266.private

&lt;span class="c1"&gt;# On indique que la clé doit être supprimée dans 6 jours&lt;/span&gt;
$ dnssec-settime -D +6d Kexample.tld.+008+25266.key
./Kexample.tld.+008+25266.key
./Kexample.tld.+008+25266.private

$ &lt;span class="c1"&gt;# On ajuste les permissions pour que bind puisse toujours lire les clés&lt;/span&gt;
$ chmod g+r *
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Bind fait normalement le nécessaire ensuite.&lt;/p&gt;
&lt;p&gt;Pour le remplacement de la KSK, il y a 2 étapes de plus : d'une part il faut révoquer immédiatement la clé, d'autre part, il faut publier auprès de son registrar les enregistrements DS correspondant à la nouvelle KSK :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ &lt;span class="c1"&gt;# Génération de la nouvelle KSK&lt;/span&gt;
$ dnssec-keygen -a RSASHA256 -f KSK -b &lt;span class="m"&gt;2048&lt;/span&gt; example.tld
Generating key pair...+++ .............................................................................+++ 
Kexample.tld.+008+14614

$ &lt;span class="c1"&gt;# Révocation immédiate de la KSK&lt;/span&gt;
$ dnssec-settime -R +0 Kexample.tld.+008+17107.key
dnssec-settime: warning: Permissions on the file ./Kexample.tld.+008+17107.private have changed from &lt;span class="m"&gt;0640&lt;/span&gt; to &lt;span class="m"&gt;0600&lt;/span&gt; as a result of this operation.
./Kexample.tld.+008+17107.key
./Kexample.tld.+008+17107.private

$ &lt;span class="c1"&gt;# On indique que la clé doit être retirée dans 2 jours&lt;/span&gt;
$ dnssec-settime -I +2d Kexample.tld.+008+17107.key
./Kexample.tld.+008+17107.key
./Kexample.tld.+008+17107.private

&lt;span class="c1"&gt;# On indique que la clé doit être supprimée dans 6 jours&lt;/span&gt;
$ dnssec-settime -D +6d Kexample.tld.+008+17107.key
./Kexample.tld.+008+17107.key
./Kexample.tld.+008+17107.private

$ &lt;span class="c1"&gt;# On ajuste les permissions pour que bind puisse toujours lire les clés&lt;/span&gt;
$ chmod g+r *

$ &lt;span class="c1"&gt;# On génère les nouveaux enregistrement DS à publier chez notre registrar&lt;/span&gt;
$ dnssec-dsfromkey Kexample.tld.+008+14614.key 
example.tld. IN DS &lt;span class="m"&gt;14614&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; F14DCF5DA74A6A2727A5DF570C98BB2186CD241B
example.tld. IN DS &lt;span class="m"&gt;14614&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; B4CAF28F7BA14AA99E8C18DD87604ABBC1D18F4EE1C69D84E8BE33B7E439132F
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;On prendra évidemment bien soin de superviser le tout dans les jours qui suivent pour s'assurer que l'opération se passe bien.&lt;/p&gt;
&lt;p&gt;Une fois les 6 jours passés, on pourra supprimer les enregistrements DS de l'ancienne clé, effacer les fichiers .key et .private correspondants. Faire un peu de ménage, quoi.&lt;/p&gt;
&lt;h1 id="references"&gt;Références&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.surf.nl/binaries/content/assets/surf/en/knowledgebase/2009/rapport_200909_hardening_the_internet_DNSSSEC.pdf"&gt;http://www.surf.nl/binaries/content/assets/surf/en/knowledgebase/2009/rapport_200909_hardening_the_internet_DNSSSEC.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.surf.nl/binaries/content/assets/surf/en/knowledgebase/2012/rapport_Deploying_DNSSEC_v20.pdf"&gt;http://www.surf.nl/binaries/content/assets/surf/en/knowledgebase/2012/rapport_Deploying_DNSSEC_v20.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.nlnetlabs.nl/publications/dnssec_howto/"&gt;http://www.nlnetlabs.nl/publications/dnssec_howto/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.afnic.fr/medias/documents/DNSSEC/afnic-dnssec-howto-fr-v2.pdf"&gt;http://www.afnic.fr/medias/documents/DNSSEC/afnic-dnssec-howto-fr-v2.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.bortzmeyer.org/monitor-dnssec.html"&gt;http://www.bortzmeyer.org/monitor-dnssec.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.bortzmeyer.org/tests-dns.html"&gt;http://www.bortzmeyer.org/tests-dns.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:bortzmeyer"&gt;
&lt;p&gt;&lt;a href="https://twitter.com/bortzmeyer/status/473350103584231424"&gt;https://twitter.com/bortzmeyer/status/473350103584231424&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:bortzmeyer" rev="footnote" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</summary><category term="linux"></category><category term="bind"></category><category term="dnssec"></category></entry><entry><title>Réflexions sur l'idempotence et les déploiements automatisés</title><link href="https://blog.blaisot.org/idempotence-deploiements-automatises.html" rel="alternate"></link><published>2014-01-24T21:00:00+01:00</published><updated>2014-01-24T21:00:00+01:00</updated><author><name>sblaisot</name></author><id>tag:blog.blaisot.org,2014-01-24:idempotence-deploiements-automatises.html</id><summary type="html">&lt;h1 id="lidempotence-mais-quest-ce-que-cest-quoi-ca"&gt;L'idempotence ? Mais qu'est-ce que c'est quoi ça ?&lt;/h1&gt;
&lt;p&gt;L'idempotence est une propriété d'un traitement mathématique ou informatique qui donne le même résultat (état final) quel que soit le nombre de fois où il est appliqué à un état de départ.
En mathématique, par exemple, les fonctions suivantes sont idempotentes :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;f(x)=x+0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;f(x)=x*1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;f(x)=x*0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;f(x)&lt;/code&gt; est donc une fonction idempotente si &lt;code&gt;f(x)=f(f(x))=f(f(f(x)))=...&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;En informatique, un traitement appliqué à un état de départ et aboutissant à un état final donne toujours le même résultat final s'il est appliqué plusieurs fois.
Ainsi, si la condition d'idempotence est respectée, un script de déploiement (d'un système, d'une configuration, d'une application) pourra être lancé plusieurs fois de suite (pour vérifier qu'il marche vraiment bien, parce qu'on a ajouté le truc oublié et qu'on ne veut pas repartir de zéro, ou simplement parce que le mec chargé de lancer le script est un boulet et a oublié qu'il vient de le faire 3 minutes avant).&lt;/p&gt;
&lt;p&gt;Un traitement informatique peut être idempotent s'il respecte un de ces 3 principes :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;il vérifie au début de son exécution si il a déjà été appliqué et ne fait rien dans ce cas&lt;/li&gt;
&lt;li&gt;il commence par faire l'opération inverse de ce qu'il va finalement faire (par exemple supprimer les lignes de conf si elles sont présentes pour les ajouter ensuite)&lt;/li&gt;
&lt;li&gt;il n'utilise par design que des fonctions, commandes, sous-ensembles eux-mêmes idempotents suivant les 2 principes ci-dessus&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="a-propos-des-deploiements-automatises"&gt;À propos des déploiements automatisés&lt;/h1&gt;
&lt;p&gt;Je n'essaierai pas de vous convaincre ici de l'utilité d'automatiser les déploiements (agilité, reproductibilité, rapidité, ...), je considère ce point comme acquis. Cela nécessiterait un article à part entière.&lt;/p&gt;
&lt;p&gt;Nous partons donc du principe que, à minima, vous automatisez/scriptez/utilisez un système de gestion de configuration/whatever pour vos déploiements.
J'utiliserai ci-dessous plusieurs fois le terme de script de déploiement. Si le système que vous utilisez n'est pas un script à proprement parler mais un framework/application/ce que vous voulez, faites le parallèle, ça marche aussi.&lt;/p&gt;
&lt;p&gt;Oui, mais quels déploiements ?&lt;/p&gt;
&lt;p&gt;À vrai dire, peu importe. L'idéal, bien sûr, étant que tous les déploiements, à partir de la machine physique vierge jusqu'à l'application en production soient automatisés.
C'est le fantasme du "chouette, je viens d'avoir une nouvelle machine, je branche, j'appuie sur le gros bouton déploiement et hop, dans 5 minutes, mon service est en prod". &lt;/p&gt;
&lt;p&gt;Ainsi, on peut automatiser le déploiement de l'hyperviseur sur une machine physique, la création des machines virtuelles (l'enveloppe), le déploiement des OS dans les machines virtuelles, leur configuration, le déploiement des middlewares nécessaires au fonctionnement de l'application et leur configuration, le déploiement de l'application, etc...&lt;/p&gt;
&lt;p&gt;Et bien sûr, on souhaite le faire non pas sur un seul et unique système, mais sur un système de systèmes (oui, des équipements réseaux, des frontaux, des bases de données, des cluster nosql, des serveurs de web services, ... tout ça en même temps pour déployer non pas une application, mais un service)&lt;/p&gt;
&lt;p&gt;Un script de déploiement, c'est avant tout du code.&lt;/p&gt;
&lt;p&gt;Nous devons donc le considérer comme du code et le traiter comme tel. Et donc appliquer les mêmes méthodes de développement que pour une application :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gérer nos outils de déploiement dans un système de gestion de version (cvs pour les dinosaures, svn, git, bazaar, ...)&lt;/li&gt;
&lt;li&gt;Faire des tests unitaires&lt;/li&gt;
&lt;li&gt;Pourquoi pas de l'intégration continue, surtout si notre outil de déploiement est modulaire et réutilisable&lt;/li&gt;
&lt;li&gt;Et on peut aussi y appliquer les méthodes agile (oui, bon, on est pas obligé non plus de faire des planning games et des stand-up meetings, je déteste faire une réunion debout, mais on peut se poser autour d'une bière pour disserter de l'étape suivante)&lt;/li&gt;
&lt;li&gt;Surtout, on doit décrire les exigences. Et l'idempotente fait partie de ces exigences.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="pourquoi-en-avons-nous-besoin"&gt;Pourquoi en avons-nous besoin ?&lt;/h1&gt;
&lt;p&gt;Les outils/scripts/... de déploiement se doivent d'être idempotents.&lt;/p&gt;
&lt;p&gt;Cette affirmation très péremptoire provient de l'observation de plusieurs problématiques rencontrées dans la vraie vie. Pas celle des bisounours, celle des vrais gens. Et dans cette vie-là, vous trouvez :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;des développeurs de scripts de déploiement qui oublient les sorties/affichages pour la personne qui exécutera le déploiement et des angoissés qui pour être certains que le déploiement a bien été fait le relanceront une seconde fois même si c'est écrit en rouge, taille 48, police comic sans dans la doc qu'il ne faut pas le faire&lt;/li&gt;
&lt;li&gt;des corrections en live/de dernière minute du dernier morceau de déploiement, au moment du passage en prod et qu'on n'a pas envie de repartir de zéro en désinstallant tout et qu'on se contente de relancer globalement le déploiement (oui, c'est crade...)&lt;/li&gt;
&lt;li&gt;des étourdis qui ne se souviennent plus après leur café qu'ils ont déjà lancé un déploiement avant de partir en pause et qui recommencent&lt;/li&gt;
&lt;li&gt;... complétez avec vos propres expériences ...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note : oui, je sais, ce n'est pas forcément un humain qui doit lancer le déploiement, mais c'est pareil, l'humain peut aussi relancer le truc qui lance les déploiements, ou décider de le rejouer juste pour voir parce qu'il est... humain.&lt;/p&gt;
&lt;p&gt;D'autre part, c'est agréable, lorsqu'on développe un programme, de pouvoir le lancer plein de fois pour le tester ou tester les nouveaux morceaux, et que comme on est excité de découvrir ce qu'on a fait de bien (ou pas), on ne veut pas perdre du temps à recréer les conditions initiales idéales pour relancer son truc.&lt;/p&gt;
&lt;p&gt;Enfin (mais la liste n'est pas exhaustive), plus on aura eu de cas tordu, récupérés par notre fameuse idempotence, plus on aura un déploiement robuste et moins on aura de problème au moment du passage -en prod- à l'étape suivante.&lt;/p&gt;
&lt;p&gt;Donc, les déploiements automatiques se doivent d'être idempotents dans leur ensemble, on doit pouvoir les lancer plusieurs fois de suite sans impact sur le résultat final.&lt;/p&gt;
&lt;p&gt;Mais ils doivent aussi être idempotents dans leurs sous-parties, parfois jusqu'au niveau de la commande unitaire. Si par exemple je crée un script de déploiement d'une appli qui installe sur un OS &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;apache&lt;/li&gt;
&lt;li&gt;PHP (remplacez par l'interpréteur que vous préférez)&lt;/li&gt;
&lt;li&gt;les confs qui vont bien&lt;/li&gt;
&lt;li&gt;l'appli&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;et qu'ensuite, disons dans une version N+1, j'ai besoin d'ajouter une base mysql, je veux pouvoir ajouter mon morceau de code qui déploie mysql et relancer le tout dans son ensemble. Je m'attends alors à ce que ma base de données soit déployée mais que le reste, qui était déjà installé ne soit pas cassé.&lt;/p&gt;
&lt;h1 id="dans-la-pratique"&gt;Dans la pratique&lt;/h1&gt;
&lt;p&gt;Dans la pratique, quelques opérations unitaires sur une machine ont l'air idempotentes. Par exemple l'installation d'un package :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;aptitude update &amp;amp;&amp;amp; aptitude install -y monpackage
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Je peux lancer cette commande plusieurs fois, j'aurais toujours le même résultat final, le paquet sera installé.&lt;/p&gt;
&lt;p&gt;Sûr ? Certain ? Y compris si entre les deux invocations il y a eu une mise à jour du package sur mon dépôt ?&lt;/p&gt;
&lt;p&gt;Si ce n'est pas garanti, il vaudrait mieux le modifier légèrement pour le garantir quand c'est possible, ou connaitre (et communiquer) les limites de son script de déploiement.&lt;/p&gt;
&lt;p&gt;D'autres commandes échouent simplement si le résultat attendu est déjà présent. Il suffit de gérer l'exception et le tour est joué. Pensez à useradd par exemple qui ne créera pas l'utilisateur s'il existe déjà.&lt;/p&gt;
&lt;p&gt;Enfin, pour tout le reste, on peut coder soi-même une vérification d'existence du résultat attendu avant l'appel à la commande qui va produire ce résultat.
Par exemple, je peux faire un ls avant de créer un fichier pour voir s'il n'existe pas déjà, ou chercher la ligne de conf que je veux ajouter pour savoir si c'est vraiment nécessaire, etc...
et si ce test réussi, alors je n'ai plus rien à faire, je saute ce morceau.&lt;/p&gt;
&lt;p&gt;C'est tout ? C'est aussi simple ? Ah bin oui, mais non car dans ce cas, on ne vérifie pas que le contenu est correct.&lt;/p&gt;
&lt;p&gt;Dans mon exemple d'application LAMP, mon script de déploiement installe et configure apache. Et comme je veux garantir l'idempotence, j'ai ajouté avant l'installation d'apache une vérification, qu'il n'est pas déjà installé, sinon je saute cette partie.&lt;/p&gt;
&lt;p&gt;Maintenant, que se passe-t-il si apache est installé, mais qu'il est tout cassé ? Par exemple, après un premier déploiement, j'ai fait un rm -rf /etc/apache2 (juste pour le fun, hein, personne ne ferait une chose pareille en vrai :-p ).&lt;/p&gt;
&lt;p&gt;Mon script va vérifier si le paquet est installé, comme il est installé, il ne va rien faire, et mon déploiement ne va pas bien se passer du tout.&lt;/p&gt;
&lt;p&gt;Vérifier partiellement l'existence du résultat final ne permet pas de garantir que nous avons TOUT le résultat final.&lt;/p&gt;
&lt;p&gt;Humm, une solution pourrait être dans ce cas de prévoir dans notre script de déploiement une suppression, un retour à l'état initial "vierge" avant le déploiement.&lt;/p&gt;
&lt;p&gt;Là encore, c'est trop simple, tout simplement parce que d'une part, défaire systématiquement pour refaire la même chose est inefficace, on ne veut pas pénaliser 99% des lancements pour gérer les 1% de cas tordus, d'autre part on risque de casser autre chose. Par exemple la modif qui a été appliquée en prod et non reportée dans le script de déploiement (qui a dit bien fait ?) ou la seconde appli installée sur le même serveur et qui n'est pas gérée par le même script de déploiement (qui a répété bien fait ?).&lt;/p&gt;
&lt;p&gt;La vrai bonne réponse est que le développeur du script de déploiement doit s'adapter à l'environnement cible et user d'un savant mélange de ces 2 techniques (vérification d'exécution préalable ou désinstallation préalable) suivant le contexte. Il doit également poser lui-même ses conditions sur l'état initial que son script de déploiement peut accepter ou non.&lt;/p&gt;
&lt;p&gt;Alors, maintenant que nos script de déploiements sont idempotents, c'est le bonheur... ou pas.&lt;/p&gt;
&lt;h1 id="pourquoi-cela-ne-suffit-pas"&gt;Pourquoi cela ne suffit pas&lt;/h1&gt;
&lt;p&gt;Repartons du besoin. Lorsqu'on crée un script de déploiement c'est pour obtenir comme résultat final un bouzin fonctionnel. Et on sait qu'il sera fonctionnel si tel et tel prérequis est respecté. Notre script de déploiement a donc pour mission de mettre en place ces prérequis. Nous cherchons donc, en plus de l'idempotence nécessaire, à obtenir un état final constant quel que soit l'état initial.&lt;/p&gt;
&lt;p&gt;En d'autres termes, ce qu'on cherche, c'est que notre script de déploiement f, peu importe l'état initial x, donne toujours le résultat c.
&lt;code&gt;f(x)=c&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Je ne connais pas le nom de cette propriété, malheureusement, mais s'il y a des plus matheux que moi dans le coin, n'hésitez pas à compléter en commentaire.&lt;/p&gt;
&lt;p&gt;Cela tombe bien, parce que ce type de fonction est aussi idempotent.&lt;/p&gt;
&lt;p&gt;Et là, je ne vois que 2 solutions pour le garantir :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Soit l'état initial est le vide absolu. Dans ce cas, comme on construit tout, on est certain de ce qu'on obtient. il faut donc partir de l'installation de l'OS (on supposera pour l'exercice qu'en dessous de l'OS, c'est le vide absolu. C'est un peu réducteur mais on est certain que l'OS vierge d'installation est reproductible aisément)&lt;/li&gt;
&lt;li&gt;Soit nous sommes obligés d'imposer des prérequis, de poser des exigences sur l'état initial.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="en-conclusion"&gt;En conclusion&lt;/h1&gt;
&lt;p&gt;L'art noble et délicat du développement d'un script de déploiement doit respecter quelques principes :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Edicter et documenter les exigences ou prérequis à l'exécution de ce script (il est d'ailleurs mieux de les vérifier au lancement)&lt;/li&gt;
&lt;li&gt;Être idempotent dans son ensemble&lt;/li&gt;
&lt;li&gt;Être idempotent dans ses sous-parties&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Enfin, et surtout, la qualité du déploiement utilisé dépend principalement de l'humain qui l'a codé, de sa maitrise technique, et de sa capacité à anticiper les cas problématiques plutôt qu'à les découvrir à l'utilisation.&lt;/p&gt;</summary><category term="devops"></category><category term="déploiement"></category><category term="automatisation"></category></entry><entry><title>Feuilletés au foie-gras et à la mangue</title><link href="https://blog.blaisot.org/feuilletes-foie-gras-mangue.html" rel="alternate"></link><published>2013-12-31T16:00:00+01:00</published><updated>2013-12-31T16:00:00+01:00</updated><author><name>sblaisot</name></author><id>tag:blog.blaisot.org,2013-12-31:feuilletes-foie-gras-mangue.html</id><summary type="html">

&lt;p&gt;Aujourd'hui, j'ai réalisé des feuilletés au foie-gras et à la mangue pour l'apéro du nouvel an et je me suis dit que je partagerai bien la recette avec vous. La voici donc :&lt;/p&gt;


&lt;h1 id="ingredients"&gt;Ingrédients&lt;/h1&gt;
&lt;h2 id="pour-la-confiture-de-mangue"&gt;Pour la confiture de mangue :&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Une mangue bien mûre&lt;/li&gt;
&lt;li&gt;Du sucre (même poids que la mangue épluchée)&lt;/li&gt;
&lt;li&gt;Un peu d’eau (5 à 10 cl)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="pour-les-feuilletes"&gt;Pour les feuilletés&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Pâte feuilletée (achetée toute prête ou faite maison, mais à conserver au réfrigérateur pour la travailler froide)&lt;/li&gt;
&lt;li&gt;Des tranches de foie-gras entier (pas de bloc, cela fond à la cuisson)&lt;/li&gt;
&lt;li&gt;Un jaune d’œuf&lt;/li&gt;
&lt;li&gt;Fleur de sel, poivre&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="realisation"&gt;Réalisation&lt;/h1&gt;
&lt;h2 id="la-confiture-de-mangue"&gt;La confiture de mangue&lt;/h2&gt;
&lt;p&gt;Éplucher la mangue, retirer le noyau central et couper la pulpe en dés.
Réaliser une confiture en faisant cuire 20 minutes dans une casserole à feu moyen la mangue avec un peu d’eau, puis ajoutez le sucre et laissez cuire 10 minutes supplémentaires en remuant régulièrement afin d’éviter que cela ne colle au fond de la casserole.
Laissez refroidir, puis mettre au réfrigérateur 2h.&lt;/p&gt;
&lt;h2 id="les-feuilletes"&gt;Les feuilletés&lt;/h2&gt;
&lt;p&gt;Lorsque la confiture de mangue est bien froide :
Préchauffez votre four à 180°C&lt;/p&gt;
&lt;p&gt;Étalez la pâte feuilletée et découpez à l’emporte-pièce de jolies formes. Suivant la taille, vous obtiendrez des amuse-bouche pour l’apéritif ou une entrée.&lt;/p&gt;
&lt;p&gt;&lt;img alt="img2" src="/static/img/feuilletes-foie-gras/image002.jpg" title="img2" /&gt;&lt;/p&gt;
&lt;p&gt;Disposez-les sur une tôle de four recouverte d’un papier cuisson.&lt;/p&gt;
&lt;p&gt;&lt;img alt="img4" src="/static/img/feuilletes-foie-gras/image004.jpg" title="img4" /&gt;&lt;/p&gt;
&lt;p&gt;Ajouter un morceau de foie-gras en veillant à ce qu’il reste au moins 3mm de pâte autour&lt;/p&gt;
&lt;p&gt;&lt;img alt="img6" src="/static/img/feuilletes-foie-gras/image006.jpg" title="img6" /&gt;&lt;/p&gt;
&lt;p&gt;Afin d’obtenir une belle dorure à la cuisson, badigeonnez de jaune d’œuf au pinceau autour du foie-gras&lt;/p&gt;
&lt;p&gt;&lt;img alt="img8" src="/static/img/feuilletes-foie-gras/image008.jpg" title="img8" /&gt;&lt;/p&gt;
&lt;p&gt;Ajoutez une petite touche de confiture de mangue.
Celle-ci peut être remplacée par un morceau de figue fraiche, ou même un morceau de mangue mais elle doit dans ce cas être très sucrée et ne pas apporter d’acidité qui ne se marie pas très bien avec le foie-gras.
Ajoutez un peu de poivre du moulin et un grain de fleur de sel.&lt;/p&gt;
&lt;p&gt;&lt;img alt="img10" src="/static/img/feuilletes-foie-gras/image010.jpg" title="img10" /&gt;&lt;/p&gt;
&lt;p&gt;Mettez la tôle au four 10 minutes à 180°C. Ne pas ouvrir la porte du four pendant la cuisson, vous risqueriez de voir le feuilletage retomber.&lt;/p&gt;
&lt;p&gt;&lt;img alt="img12" src="/static/img/feuilletes-foie-gras/image012.jpg" title="img12" /&gt;&lt;/p&gt;
&lt;p&gt;Disposez dans une assiette de présentation et régalez-vous. Ils se mangent tiède, ou à température ambiante.&lt;/p&gt;
&lt;p&gt;&lt;img alt="img14" src="/static/img/feuilletes-foie-gras/image014.jpg" title="img14" /&gt;&lt;/p&gt;
&lt;p&gt;Et voilà, bon réveillon à tous !&lt;/p&gt;</summary><category term="recette"></category><category term="feuilletés"></category><category term="foie-gras"></category><category term="mangue"></category><category term="fêtes"></category></entry><entry><title>Migration d'apache 2.2 + mod_auth_mysql vers 2.4 + mod_authn_dbd</title><link href="https://blog.blaisot.org/apache-mysql-auth.html" rel="alternate"></link><published>2013-12-06T21:00:00+01:00</published><updated>2013-12-06T21:00:00+01:00</updated><author><name>sblaisot</name></author><id>tag:blog.blaisot.org,2013-12-06:apache-mysql-auth.html</id><summary type="html">

&lt;p&gt;Depuis longtemps, une partie de mon serveur web, servi par un apache 2.2, était protégée par une authentification de type basique dont la base d'utilisateurs se trouvent dans une table mysql. Lors de l'upgrade du serveur en Ubuntu 13.10, apache est passé de la version 2.2 à la version 2.4.&lt;/p&gt;
&lt;p&gt;Et soudain, c'est le drame.
De grands changements on eu lieu du côté des modules d'authentification en général et celui gérant les bases mysql comme base d'utilisateurs en particulier.&lt;/p&gt;


&lt;h2 id="creation-de-la-table-dutilisateur"&gt;Création de la table d'utilisateur&lt;/h2&gt;
&lt;p&gt;Avant toute chose, il faut une table d'utilisateurs. Pour l'exercice, nous allons créer une base &lt;code&gt;apache_auth&lt;/code&gt;, créer un utilisateur mysql &lt;code&gt;username&lt;/code&gt; et son mot de passe &lt;code&gt;password&lt;/code&gt; pouvant lire le contenu des tables de cette base.
Puis créer la table &lt;code&gt;utilisateurs&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;apache_auth&lt;/span&gt; &lt;span class="k"&gt;CHARACTER&lt;/span&gt; &lt;span class="kt"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;UTF8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Query&lt;/span&gt; &lt;span class="n"&gt;OK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="nf"&gt;affected&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;apache_auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;username&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;IDENTIFIED&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;password&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Query&lt;/span&gt; &lt;span class="n"&gt;OK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="nf"&gt;affected&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;apache_auth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;Database&lt;/span&gt; &lt;span class="n"&gt;changed&lt;/span&gt;
&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="k"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="ss"&gt;`utilisateurs`&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;       &lt;span class="ss"&gt;`login`&lt;/span&gt; &lt;span class="kt"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="no"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;       &lt;span class="ss"&gt;`pass`&lt;/span&gt; &lt;span class="kt"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="no"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;       &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="ss"&gt;`login`&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;`login`&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;       &lt;span class="kp"&gt;ENGINE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MyISAM&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="kp"&gt;CHARSET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;utf8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Query&lt;/span&gt; &lt;span class="n"&gt;OK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="nf"&gt;affected&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;desc&lt;/span&gt; &lt;span class="n"&gt;utilisateurs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;+-------+--------------+------+-----+---------+-------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt;         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;Null&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="k"&gt;Key&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="k"&gt;Default&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Extra&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+-------+--------------+------+-----+---------+-------+&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;NO&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;PRI&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;NULL&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;pass&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;NO&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;NULL&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;       &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+-------+--------------+------+-----+---------+-------+&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kt"&gt;set&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="n"&gt;sec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;On peut ensuite y mettre un utilisateur pour apache dont le login est &lt;code&gt;joe&lt;/code&gt; et le mot de passe est &lt;code&gt;jwja&lt;/code&gt;.&lt;sup id="fnref:dalton"&gt;&lt;a class="footnote-ref" href="#fn:dalton" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt; Les commandes de hachage mysql n'étant pas forcément bien compatible avec apache, on utilise htpasswd pour hacher le mot de passe.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ mysql -u root -p -e &lt;span class="s2"&gt;&amp;quot;INSERT INTO utilisateurs (login, pass) VALUES (\&amp;quot;joe\&amp;quot;,\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;htpasswd -nb joe jwja &lt;span class="p"&gt;|&lt;/span&gt;cut -d &lt;span class="s1"&gt;&amp;#39;:&amp;#39;&lt;/span&gt; -f 2&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;\&amp;quot;)&amp;quot;&lt;/span&gt; apache_auth
Enter password:
$
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;et même vérifier le tout&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$ mysql -u root -p -e &lt;span class="s2"&gt;&amp;quot;SELECT * FROM apache_auth.utilisateurs;&amp;quot;&lt;/span&gt;
Enter password:
+-------+---------------------------------------+
&lt;span class="p"&gt;|&lt;/span&gt; login &lt;span class="p"&gt;|&lt;/span&gt; pass                                  &lt;span class="p"&gt;|&lt;/span&gt;
+-------+---------------------------------------+
&lt;span class="p"&gt;|&lt;/span&gt; joe   &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;$apr1$7&lt;/span&gt;jO4MTja&lt;span class="nv"&gt;$pd2pAH6WkYfcyrzPhgLcX&lt;/span&gt;/ &lt;span class="p"&gt;|&lt;/span&gt;
+-------+---------------------------------------+
$
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;et voilà, nous sommes prêts&lt;/p&gt;
&lt;h2 id="configuration-avec-apache-22-et-le-mod_auth_mysql"&gt;Configuration avec apache 2.2 et le mod_auth_mysql&lt;/h2&gt;
&lt;p&gt;Sous Ubuntu 13.04 (en apache 2.2 donc), voici quelle était ma configuration :
Dans la directive &lt;code&gt;&amp;lt;Directory&amp;gt;&lt;/code&gt; d'apache, simplement un&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;AllowOverride&lt;/span&gt; AuthConfig
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Puis dans le .htaccess du répertoire, ceci :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;AuthType&lt;/span&gt; Basic
&lt;span class="nb"&gt;AuthName&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;mon super espace protégé&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;AuthBasicAuthoritative&lt;/span&gt; &lt;span class="k"&gt;off&lt;/span&gt;
&lt;span class="nb"&gt;AuthMySQLAuthoritative&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt;
&lt;span class="nb"&gt;AuthMYSQLEnable&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt;
&lt;span class="nb"&gt;AuthMySQLHost&lt;/span&gt; localhost
&lt;span class="nb"&gt;AuthMySQLUser&lt;/span&gt; username
&lt;span class="nb"&gt;AuthMySQLPassword&lt;/span&gt; password
&lt;span class="nb"&gt;AuthMySQLDB&lt;/span&gt; apache_auth
&lt;span class="nb"&gt;AuthMySQLUserTable&lt;/span&gt; utilisateurs
&lt;span class="nb"&gt;AuthMySQLNameField&lt;/span&gt; login
&lt;span class="nb"&gt;AuthMySQLPasswordField&lt;/span&gt; pass
&lt;span class="nb"&gt;AuthMySQLPwEncryption&lt;/span&gt; md5

&lt;span class="nb"&gt;Require&lt;/span&gt; valid-user

&lt;span class="nt"&gt;&amp;lt;LIMIT&lt;/span&gt; &lt;span class="s"&gt;GET POST PUT&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nb"&gt;require&lt;/span&gt; valid-user
&lt;span class="nt"&gt;&amp;lt;/LIMIT&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Bien sûr, un petit coup de &lt;code&gt;a2enmod auth_mysql&lt;/code&gt; était nécessaire.&lt;/p&gt;
&lt;p&gt;That's all.&lt;/p&gt;
&lt;h2 id="configuration-avec-apache-24-et-le-mod_authn_dbd"&gt;Configuration avec apache 2.4 et le mod_authn_dbd&lt;/h2&gt;
&lt;p&gt;Là, ça se corse.
Dans le &lt;code&gt;&amp;lt;VirtualHost&amp;gt;&lt;/code&gt; il faut définir les paramètres du driver sql :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;        &lt;span class="nb"&gt;DBDriver&lt;/span&gt; mysql
        &lt;span class="nb"&gt;DBDParams&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;socket=/var/run/mysqld/mysqld.sock dbname=apache_auth user=username pass=password&amp;quot;&lt;/span&gt;
        &lt;span class="nb"&gt;DBDMin&lt;/span&gt;  &lt;span class="m"&gt;4&lt;/span&gt;
        &lt;span class="nb"&gt;DBDKeep&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;
        &lt;span class="nb"&gt;DBDMax&lt;/span&gt;  &lt;span class="m"&gt;20&lt;/span&gt;
        &lt;span class="nb"&gt;DBDExptime&lt;/span&gt; &lt;span class="m"&gt;300&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Puis dans le &lt;code&gt;&amp;lt;Directory&amp;gt;&lt;/code&gt; ajouter :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;                &lt;span class="nb"&gt;AuthName&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;mon super espace protégé&amp;quot;&lt;/span&gt;
                &lt;span class="nb"&gt;AuthType&lt;/span&gt; Basic
                &lt;span class="nb"&gt;AuthBasicProvider&lt;/span&gt; dbd
                &lt;span class="c"&gt;# Requete SQL pour l&amp;#39;authentification&lt;/span&gt;
                &lt;span class="nb"&gt;AuthDBDUserPWQuery&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;SELECT pass FROM utilisateurs WHERE login = %s&amp;quot;&lt;/span&gt;
                &lt;span class="nb"&gt;Require&lt;/span&gt; valid-user
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Je n'ai pas creusé davantage pour déporter les directives dans le .htaccess, mais la définition du driver mysql ne me semble pas pouvoir se déporter facilement de cette manière (disons que je n'ai pas trouvé du premier coup et que je n'avais pas le temps de débugguer).&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:dalton"&gt;
&lt;p&gt;Joe utilise un mot de passe faible créé à partir de l'initiale du prénom des 4 frères, les 3 autres étant William, Jack et Averell. Dans la vraie vie, le mot de passe ressemblerait plus à ceci :&lt;code&gt;d3F@j5(éF(c54)+F'Dfc23&lt;/code&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:dalton" rev="footnote" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</summary><category term="linux"></category><category term="apache"></category><category term="authentification"></category><category term="mysql"></category></entry><entry><title>SSL/TLS hardening for apache 2.4</title><link href="https://blog.blaisot.org/ssl-hardening.html" rel="alternate"></link><published>2013-11-30T11:30:00+01:00</published><updated>2013-11-30T11:30:00+01:00</updated><author><name>sblaisot</name></author><id>tag:blog.blaisot.org,2013-11-30:ssl-hardening.html</id><summary type="html">

&lt;p&gt;Je suis tombé au détour du web sur un super outil de test de votre serveur httpS qui vous dit tous les protocoles et "cipher suites" que votre serveur autorise, ainsi que les cipher suites utilisée par chaque navigateur.
Vous pouvez tester votre site httpS ici : &lt;a href="https://www.ssllabs.com/ssltest/"&gt;https://www.ssllabs.com/ssltest/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Evidemment, en ce qui me concerne, avec la configuration par défaut, le résultat n'a pas été très glorieux :
&lt;img alt="ssl_before" src="/static/img/ssl_before.jpg" title="ssl_before" /&gt;&lt;/p&gt;
&lt;p&gt;Donc, la question, c'est quelle est "la bonne" configuration à appliquer à son serveur apache pour faire du SSL qui soit un minimum mieux sécurisé que la configuration par défaut.&lt;/p&gt;


&lt;p&gt;Et la réponse, bien évidemment, c'est "ça dépend". En particulier, cela dépend des visiteurs que vous adressez, de votre capacité à leur imposer un nbavigateur plutôt qu'un autre (et même un OS plutôt qu'un autre), en fonction des protocoles implémentés par les différents navigateurs.&lt;/p&gt;
&lt;p&gt;Déjà, vous pourrez retrouver les "best practice" décrites dans ce document : &lt;a href="https://www.ssllabs.com/downloads/SSL_TLS_Deployment_Best_Practices_1.3.pdf"&gt;https://www.ssllabs.com/downloads/SSL_TLS_Deployment_Best_Practices_1.3.pdf&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Pour la mise en oeuvre, je vous conseille d'appliquer la configuration suivante dans votre apache :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;SSLProtocol&lt;/span&gt; &lt;span class="k"&gt;all&lt;/span&gt; -SSLv2 -SSLv3
&lt;span class="nb"&gt;SSLHonorCipherOrder&lt;/span&gt; &lt;span class="k"&gt;On&lt;/span&gt;
&lt;span class="nb"&gt;SSLCipherSuite&lt;/span&gt; ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;et là, TADAAAA, magie du spectacle, le résultat est bien meilleur :
&lt;img alt="ssl_after" src="/static/img/ssl_after.jpg" title="ssl_after" /&gt;&lt;/p&gt;
&lt;p&gt;Le revers de la médaille, c'est que vous vous privez des clients sous IE6 sur windows XP. Cela me semble acceptable comme compromis, ce navigateur n'étant déjà plus supporté par la plupart des sites, mais si vous devez continuer à garantir le fonctionnement de votre site pour ce navigateur, il suffit de laisser le protocole sslv3 comme ceci :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;SSLProtocol&lt;/span&gt; &lt;span class="k"&gt;all&lt;/span&gt; -SSLv2
&lt;/pre&gt;&lt;/div&gt;</summary><category term="linux"></category><category term="apache"></category><category term="ssl"></category></entry><entry><title>[Astuce] Eviter de mettre une commande dans l'historique du shell</title><link href="https://blog.blaisot.org/history-tip.html" rel="alternate"></link><published>2013-10-12T18:00:00+02:00</published><updated>2013-10-12T18:00:00+02:00</updated><author><name>sblaisot</name></author><id>tag:blog.blaisot.org,2013-10-12:history-tip.html</id><summary type="html">

&lt;p&gt;Parfois, parce qu'on a pas le choix, on doit passer un mot de passe en argument d'une commande. Et bien sûr, en bon parano, on ne souhaite pas que ce mot de passe finisse enregistré dans l'historique du shell.&lt;/p&gt;


&lt;p&gt;Par exemple, la dernière fois que cela m'est arrivé, c'était pour définir le proxy :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;HTTP_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://user:PASSWORD@proxy:port/&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Jusqu'à présent, je prenais soin d'empêcher tout bonnement l'enregistrement de l'historique sur disque à la fin de la session avec un &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;unset&lt;/span&gt; HISTFILE
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Redoutablement efficace, mais cela a tout de même l'inconvénient d'être un peu violent : aucun historique de la session n'est gardé. 
En plus, tant qu'on ne s'est pas déconnecté, c'est quand même toujours dans l'historique (en mémoire).&lt;/p&gt;
&lt;p&gt;La solution plus propre, pour éviter qu'une commande ne soit enregistrée dans l'historique, c'est simplement de la faire précéder par... une espace&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;user@localhost:~#&lt;/span&gt; █export &lt;span class="nv"&gt;HTTP_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://user:PASSWORD@proxy:port/&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Ainsi, la commande n'est pas enregistrée dans l'historique, ni en mémoire, ni sur disque à la fin de la session, mais toutes les autres commandes y seront.&lt;/p&gt;
&lt;p&gt;Cela fonctionne avec zsh nativement, et avec bash en fonction de la configuration. Par défaut, c'est activé sur ubuntu 13.04, si ce n'est pas le cas dans votre bash, cela s'active en ajoutant ignorespace à la variable HISTCONTROL&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nv"&gt;HISTCONTROL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ignorespace 
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Je vous recommande par ailleurs la découverte de cette variable HISTCONTROL en lisant &lt;a href="http://voidandany.free.fr/index.php/astuce-bash-la-variable-histcontrol/"&gt;http://voidandany.free.fr/index.php/astuce-bash-la-variable-histcontrol/&lt;/a&gt;&lt;/p&gt;</summary><category term="linux"></category><category term="shell"></category><category term="tips"></category></entry><entry><title>dedibox IPv6 reloaded</title><link href="https://blog.blaisot.org/dedibox-ipv6-reloaded.html" rel="alternate"></link><published>2013-09-14T21:00:00+02:00</published><updated>2013-09-14T21:00:00+02:00</updated><author><name>sblaisot</name></author><id>tag:blog.blaisot.org,2013-09-14:dedibox-ipv6-reloaded.html</id><summary type="html">

&lt;p&gt;&lt;em&gt;Cet article fait suite à l'article précédent sur la &lt;a href="/dedibox_ipv6.html"&gt;configuration IPv6 d'une dédibox&lt;/a&gt; suite à la disponibilité de nouvelles options&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Comme vous l'avez peut-etre vu, depuis jeudi, deux nouvelles fonctionnalités IPv6 sont disponibles sur les serveurs dédiés dedibox chez online.&lt;/p&gt;
&lt;p&gt;Une nouvelle plage d'adresses IPv6 2001:xxxx:xxxx été mise en production chez online (précedemment 2a01:xxx:xxx). Ainsi, les nouveaux clients IPv6 auront des adresses dans cette plage.&lt;/p&gt;
&lt;p&gt;Vous pouvez désormais découper votre bloc d'adresses IPv6 pour le répartir sur plusieurs serveurs et vous pouvez mettre en place une résolution de nom inverse (reverse DNS) sur vos IPv6.
Ces nouvelles fonctionnalités ne sont toutefois disponible que sur la nouvelle plage d'adresses IPv6. Si vous avez un bloc d'adresses dans l'ancienne plage, vous devrez migrer vos adresses dans la nouvelle plage pour en bénéficier.&lt;/p&gt;


&lt;div class="toc"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#migrer-vers-la-nouvelle-plage"&gt;Migrer vers la nouvelle plage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#acceder-a-la-configuration-ipv6-dans-votre-console-de-gestion"&gt;Accéder à la configuration IPv6 dans votre console de gestion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#reverse-dns-ipv6"&gt;Reverse DNS IPv6&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#jai-mon-serveur-dns-bind"&gt;J'ai mon serveur DNS bind&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#les-services-en-ligne"&gt;Les services en ligne&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#decoupage-du-bloc-pour-differents-serveurs"&gt;Découpage du bloc pour différents serveurs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id="migrer-vers-la-nouvelle-plage"&gt;Migrer vers la nouvelle plage&lt;/h2&gt;
&lt;p&gt;Il n'y a pas (encore ?) de procédure simple de migration. Pour les "early adopters" qui voudraient migrer d'un bloc d'IP dans l'ancienne plage vers un bloc d'IP dans la nouvelle plage, la procédure consiste à :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;résilier votre bloc actuel&lt;/li&gt;
&lt;li&gt;commander un nouveau bloc&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Pas de crainte de perte de service néanmoins, online y a pensé et la résiliation d'une plage d'IP s'arrêtera durant la période de migration à l'aspect administratif, la partie technique continuant à fonctionner après la résiliation le temps que vous mettiez en place votre nouvelle configuration (pas de nettoyage des conf de résiliation des anciens blocs IPv6 sur les routeurs). &lt;/p&gt;
&lt;p&gt;Afin de résilier, il faut se rendre dans votre console de gestion online, rubrique compte-&amp;gt;Mes services et cliquer sur la croix rouge de résiliation au bout de la ligne "Bloc IPv6".
Et voilà, il suffit d'attendre la fin du mois que la résiliation prenne effet pour commander un nouveau bloc d'IPv6.&lt;/p&gt;
&lt;p&gt;Ah, vous êtes pressé ?
Dans ce cas, pour accélérer la résiliation, créez un ticket au support pour demander la résiliation anticipée.&lt;/p&gt;
&lt;p&gt;Ah, vous êtes encore plus pressé que ça ?
Vous pouvez alors essayer de contacter le support par IRC. Avec un peu de chance, il y aura quelqu'un de disponible pour valider immédiatement la résiliation.&lt;/p&gt;
&lt;p&gt;Une fois votre résiliation validée, il faut attendre que le lapin-cron&lt;sup id="fnref:lapin-cron"&gt;&lt;a class="footnote-ref" href="#fn:lapin-cron" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt; vienne nettoyer toute référence à votre ancienn bloc d'IPv6 pour que vous puissiez en commander un autre. Il passe 2 fois par heure, à 00 et 30.&lt;/p&gt;
&lt;p&gt;Enfin, quand vous n'avez plus de bloc d'IPv6, vous pouvez en commander un nouveau qui sera dans la nouvelle plage d'IPv6 d'online et bénéficier ainsi des nouvelles fonctionnalités.
Une fois votre nouvelle plage commandée, il faut attendre un nouveau passage du lapin-cron avant qu'elle ne soit utilisable sur votre serveur, ne supprimez pas votre ancienne configuration trop vite ou vous risquez de perdre votre connectivité IPv6.&lt;/p&gt;
&lt;h2 id="acceder-a-la-configuration-ipv6-dans-votre-console-de-gestion"&gt;Accéder à la configuration IPv6 dans votre console de gestion&lt;/h2&gt;
&lt;p&gt;Pour accéder aux nouvelles fonctionnalités dans votre console de gestion, rendez-vous dans le menu serveur-&amp;gt;configuration réseau.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Serveur-&amp;gt;configuration réseau" src="/static/img/dedibox-ipv6-reloaded-1.png" title="Serveur-&amp;gt;configuration réseau" /&gt;&lt;/p&gt;
&lt;p&gt;Votre bloc d'IPv6 y est indiqué et un petit menu déroulant à droite vous permet de déléger à vos serveurs la résolution dns inverse et de découper votre bloc pour l'affecter à différents serveurs.
&lt;img alt="configuration réseau-&amp;gt;IPv6" src="/static/img/dedibox-ipv6-reloaded-2.png" title="configuration réseau-&amp;gt;IPv6" /&gt;&lt;/p&gt;
&lt;h2 id="reverse-dns-ipv6"&gt;Reverse DNS IPv6&lt;/h2&gt;
&lt;p&gt;Contrairement à l'IPv4, les serveurs DNS d'online ne réalisent pas la résolution inverse pour vos IPv6. Néanmoins, ils peuvent déléguer à vos serveurs cette résolution afin qu'elle soit effective.
Cela nécessite d'avoir 2 serveurs DNS (probablement un master et un slave) qui réalisent cette résolution. Si vous n'avez qu'un serveur, vous pouvez faire un échange de dns secondaire avec quelqu'un ou simplement utiliser des services DNS en ligne qui pourront être slave de votre serveur.&lt;/p&gt;
&lt;h3 id="jai-mon-serveur-dns-bind"&gt;J'ai mon serveur DNS bind&lt;/h3&gt;
&lt;p&gt;Voici un exemple de configuration pour le serveur DNS bind sur votre serveur.&lt;/p&gt;
&lt;p&gt;Créez un fichier de zone &lt;code&gt;/etc/bind/db.2001&lt;/code&gt; contenant &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;;
; BIND reverse data file for IPv6 2001:xxxx:xxxx::/48
;
$TTL    3600
@       IN      SOA     monserveur.mondomaine.tld. hostmaster.mondomaine.tld. (
                        2013091202
                        8H
                        30M
                        4W
                        1H )

;
@       IN      NS      monserveur.mondomaine.tld.
@       IN      NS      secondaire.mondomaine.tld.

; IPv6 PTR entries
x.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.x.x.x.x.x.x.x.x.1.0.0.2.ip6.arpa.    IN    PTR    monserveur.mondomaine.tld.
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;à adapter à votre domaine bien sûr.
La dernière ligne correspond à une entrée reverse. L'adresse IPv6 du serveur est notée de droite à gauche avec un point séparant chaque caractère, le tout fini par ip6.arpa.&lt;/p&gt;
&lt;p&gt;Pour le reste du contenu d'un fichier de zone bind, je vous renvoie vers le &lt;a href="http://www.tldp.org/HOWTO/DNS-HOWTO.html"&gt;DNS Howto&lt;/a&gt; et cet &lt;a href="http://www.zonefile.org/?lang=en"&gt;assistant de création de fichier de zone&lt;/a&gt;. Vraisemblablement, si vous ne savez pas comment ça marche, il vaut mieux vous tourner vers un service de DNS en ligne (voir ci-dessous).&lt;/p&gt;
&lt;p&gt;Ensuite, vous devez déclarer la zone dans votre fichier de configuration &lt;code&gt;/etc/bind/named.conf.local&lt;/code&gt; sur votre DNS master&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;zone &amp;quot;x.x.x.x.x.x.x.x.1.0.0.2.ip6.arpa&amp;quot; {
        type master;
        notify yes;
        allow-transfer { x.x.x.x; 2001:xxxx:xxxx:xxxx::x; };
        file &amp;quot;/etc/bind/db.2001&amp;quot;;
};
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;"x.x.x.x.x.x.x.x.1.0.0.2.ip6.arpa&lt;/code&gt; correspond à la zone reverse de votre bloc (il s'agit de votre bloc écrit de droit à gauche en séparant chaque caractère par un point et fini par ip6.arpa).
La ligne &lt;code&gt;allow-transfer&lt;/code&gt; permet aux slave de venir chercher le contenu de la zone sur le master
La ligne &lt;code&gt;notify yes&lt;/code&gt; permet à chaque changement de notifier les slaves qu'ils doivent recharger le contenu de la zone
Enfin, la ligne &lt;code&gt;file&lt;/code&gt; référence le fichier de zone créé précédemment.&lt;/p&gt;
&lt;p&gt;Il faut également déclarer la zone sur le serveur slave :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;zone &amp;quot;x.x.x.x.x.x.x.x.1.0.0.2.ip6.arpa&amp;quot; {
        type slave;
        notify yes;
        file &amp;quot;/etc/bind/zones/db.2001&amp;quot;;
        masters { x.x.x.x; 2001:xxxx:xxxx::x; };
};
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Relancez le tout, et testez.&lt;/p&gt;
&lt;h3 id="les-services-en-ligne"&gt;Les services en ligne&lt;/h3&gt;
&lt;p&gt;Les services &lt;a href="http://dns.he.net"&gt;dns.he.net&lt;/a&gt; ou &lt;a href="http://xname.org"&gt;xname.org&lt;/a&gt; par exemple permettent de gérer des zones DNS sans posséder de serveur DNS soi-même et d'être slave de vos serveurs DNS. Je ne les ai pas encore testés personnellement pour l'instant, si j'ai le temps un jour, j'essaierai et je vous ferai un billet là-dessus.&lt;/p&gt;
&lt;h2 id="decoupage-du-bloc-pour-differents-serveurs"&gt;Découpage du bloc pour différents serveurs&lt;/h2&gt;
&lt;p&gt;Dans votre console de gestion, sous serveur-&amp;gt;configuration réseau-&amp;gt;IPv6 sélectionnez "Créer un sous-réseau".
Choisissez alors parmis les sous-réseau proposés /56 de votre bloc /48.
Un nouveau DUID est alors créé pour ce sous-réseau utilisable sur l'un de vos serveurs. Il s'utilise comme le DUID de votre bloc principal.&lt;/p&gt;
&lt;p&gt;Ces sous-réseaux /56 peuvent à nouveau être découpés en sous-sous-réseaux /64.&lt;/p&gt;
&lt;p&gt;Amusez-vous bien avec ces nouvelles fonctionnalités.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:lapin-cron"&gt;
&lt;p&gt;private-joke avec les techniciens d'online avec lesquels j'ai échangé où on comparait leur cron au lapin blanc d'Alice au pays des merveilles, celui avec sa grosse montre, toujours pressé.&amp;#160;&lt;a class="footnote-backref" href="#fnref:lapin-cron" rev="footnote" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</summary><category term="linux"></category><category term="dedibox"></category><category term="ipv6"></category></entry><entry><title>Timeout infini de grub après un boot avorté</title><link href="https://blog.blaisot.org/grub-timeout.html" rel="alternate"></link><published>2013-09-10T13:00:00+02:00</published><updated>2013-09-10T13:00:00+02:00</updated><author><name>sblaisot</name></author><id>tag:blog.blaisot.org,2013-09-10:grub-timeout.html</id><summary type="html">&lt;h1 id="le-probleme"&gt;Le problème&lt;/h1&gt;


&lt;p&gt;Si vous avez un serveur sans console hébergé un peu loin, non accessible, et sans KVM, vous pourriez avoir un problème.
Si un boot se passe mal (disons pour l'exercice que votre hébergeur, farceur, a eu une coupure de courant pendant un boot), alors grub le détecte et passe dans un mode RECORDFAIL.&lt;/p&gt;
&lt;p&gt;Cela peut également survenir sur vous cliquez sur le bouton reboot de votre console de gestion alors que le serveur est déjà en cours de reboot.&lt;/p&gt;
&lt;p&gt;Le plus drôle (façon de parler), c'est qu'à cet effet les solution dites de "monitoring proactif" peuvent avoir un effet désastreux suite à une coupure de courant, en provoquant un reboot de votre serveur pendant qu'il est justement en train de booter, et conduisant donc à un boot avorté.&lt;/p&gt;
&lt;p&gt;Et il se trouve que par défaut, sous ubuntu, lorsque cela arrive, les boot suivants ont un timeout de grub infini. Cela veut dire que votre machine ne boote pas et que grub attend une interraction sur la console... que vous n'avez pas.&lt;/p&gt;
&lt;p&gt;C'est très bien pour une machine de bureau, parce que si un boot s'est mal passé, il est important d'éviter la spirale infernale de reboot en boucle, mais pour un serveur distant sans console, c'est plus embêtant.&lt;/p&gt;
&lt;p&gt;Bref, si ça vous arrive, c'est bien la m..., votre machine ne démarre plus.&lt;/p&gt;


&lt;h1 id="les-solutions"&gt;Les solutions&lt;/h1&gt;
&lt;h2 id="la-preventive"&gt;La préventive&lt;/h2&gt;
&lt;p&gt;Pour ne pas que cela se produise, c'est assez simple, il suffit d'ajouter dans le fichier &lt;code&gt;/etc/default/grub&lt;/code&gt; la ligne suivante :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;GRUB_RECORDFAIL_TIMEOUT=3
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Puis, pour mettre à jour la configuration de grub avec ce nouveau paramètre, il suffit de faire un&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;root@localhost:~$&lt;/span&gt; sudo update-grub
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Ainsi, même après un boot infructueux, grub conservera un timeout de 3 secondes.
Et Hop, plus de plantage. Cela devrait être standard sur les distributions installées par les hébergeurs (online, OVH, ...) sur les serveurs sans KVM (entrée de gamme).&lt;/p&gt;
&lt;h2 id="la-curative"&gt;La curative&lt;/h2&gt;
&lt;p&gt;Si cela vous est déjà arrivé et que votre serveur ne boote plus, vous pouvez booter en mode rescue, monter les partitions de votre machine et supprimer de l'environnement de grub l'information recordfail de la façon suivante :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;root@rescue:/#&lt;/span&gt; mount /dev/sdaX /mnt
&lt;span class="gp"&gt;root@rescue:/#&lt;/span&gt; mount /dev/sdaY /mnt/boot
&lt;span class="gp"&gt;root@rescue:/#&lt;/span&gt; grub-editenv /mnt/boot/grub/grubenv &lt;span class="nb"&gt;unset&lt;/span&gt; recordfail
&lt;span class="gp"&gt;root@rescue:/#&lt;/span&gt; umount /mnt/boot
&lt;span class="gp"&gt;root@rescue:/#&lt;/span&gt; umount /mnt
&lt;span class="gp"&gt;root@rescue:/#&lt;/span&gt; reboot
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Il vous restera a appliquer la solution préventive ci-dessus pour ne pas que cela recommence.&lt;/p&gt;</summary><category term="linux"></category><category term="grub"></category><category term="tips"></category></entry><entry><title>Configuration IPv6 sur une dedibox sous ubuntu 13.04</title><link href="https://blog.blaisot.org/dedibox_ipv6.html" rel="alternate"></link><published>2013-09-07T14:30:00+02:00</published><updated>2013-09-07T14:30:00+02:00</updated><author><name>sblaisot</name></author><id>tag:blog.blaisot.org,2013-09-07:dedibox_ipv6.html</id><summary type="html">&lt;h1 id="principe"&gt;Principe&lt;/h1&gt;
&lt;p&gt;Pour que l'IPv6 fonctionne sur votre dédibox, il est indispensable, au préalable, de demander une plage d'IPv6.
Ceci se fait dans la &lt;a href="http://console.online.net"&gt;console&lt;/a&gt; de gestion.&lt;/p&gt;
&lt;p&gt;Il faut ensuite mettre en œuvre la délégation de préfix (PD pour &lt;em&gt;Prefix Delegation&lt;/em&gt;), c'est à dire vous authentifier auprès du routeur et lui demander de router votre préfix IPv6 vers votre dédibox.&lt;/p&gt;
&lt;p&gt;ATTENTION : Si vous possédez plusieurs dedibox, seule l'une d'entre elle pourra se connecter en IPv6.
Ceci est dû à l’implémentation choisie par online qui route toute votre classe d'IPv6 sur une seule machine.&lt;/p&gt;
&lt;p&gt;Enfin, comme pour de l'IPv4 il faut configurer une adresse IPv6 sur votre dedibox et lui indiquer le routeur par défaut (&lt;em&gt;default gateway&lt;/em&gt;)&lt;/p&gt;
&lt;div class="toc"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#principe"&gt;Principe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#commander-son-bloc-dipv6"&gt;Commander son bloc d'IPv6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#delegation-de-prefixe"&gt;Délégation de préfixe&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#installation-de-dibbler"&gt;Installation de dibbler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#configuration-de-dibbler"&gt;Configuration de dibbler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#configuration-du-firewall"&gt;Configuration du firewall&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#lancement-de-dibbler-et-lecture-des-logs"&gt;Lancement de dibbler (et lecture des logs)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#configuration-de-linterface"&gt;Configuration de l'interface&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#et-pour-ma-default-gateway"&gt;Et pour ma default Gateway ?&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#automatiquement-les-paquets-ra"&gt;Automatiquement - Les paquets RA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#manuellement-parce-que-ca-ne-marche-pas"&gt;Manuellement parce que ça ne marche pas&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#ya-plus-qua"&gt;Y'a plus qu'à&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h1 id="commander-son-bloc-dipv6"&gt;Commander son bloc d'IPv6&lt;/h1&gt;
&lt;p&gt;Une fois votre bloc IPv6 commandé, vous devez trouver dans votre console de gestion :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Votre bloc IPv6 sous la forme &lt;code&gt;2a01:0e0b:xxxx::/48&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Votre DUID, c'est à dire votre identifiant unique sur le réseau sous la forme &lt;code&gt;00:xx:xx:xx:xx:xx:xx:xx:xx:xx&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ces 2 informations vous seront indispensables&lt;/p&gt;
&lt;h1 id="delegation-de-prefixe"&gt;Délégation de préfixe&lt;/h1&gt;
&lt;p&gt;Afin de demander au routeur de router les paquets IPv6 de votre bloc vers votre serveur, il faut, en utilisant le protocole DHCPv6 vous authentifier auprès de lui.&lt;/p&gt;
&lt;h2 id="installation-de-dibbler"&gt;Installation de dibbler&lt;/h2&gt;
&lt;p&gt;Pour cela, commençons par installer dibbler (implémentaiton DHCPv6)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;root@localhost:~#&lt;/span&gt; apt-get install dibbler
&lt;span class="go"&gt;[...]&lt;/span&gt;
&lt;span class="gp"&gt;root@localhost:~#&lt;/span&gt; service dibbler-client stop
&lt;/pre&gt;&lt;/div&gt;


&lt;h2 id="configuration-de-dibbler"&gt;Configuration de dibbler&lt;/h2&gt;
&lt;p&gt;Editer / créer le fichier &lt;code&gt;/var/lib/dibbler/client-duid&lt;/code&gt;
et y mettre le DUID fourni par la console dedibox (&lt;strong&gt;garder ce DUID "secret" c'est votre identifiant pour récupérer votre /48&lt;/strong&gt;)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;   Votre bloc IPv6  0a00:0e00:0000::/48
   Duid             00:00:00:00:00:00:00:00:00:00
&lt;/pre&gt;&lt;/div&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;root@localhost:~#&lt;/span&gt; cat /var/lib/dibbler/client-duid
&lt;span class="go"&gt;00:00:00:00:00:00:00:00:00:00&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Configurez ensuite le fichier de conf &lt;code&gt;/etc/dibbler/client.conf&lt;/code&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;# Defaults for dibbler-client.
# installed at /etc/dibbler/client.conf by the maintainer scripts

duid-type duid-ll

# 8 (Debug) is most verbose. 7 (Info) is usually the best option
log-level 8

# To perform stateless (i.e. options only) configuration, uncomment
# this line below and remove any &amp;quot;ia&amp;quot; keywords from interface definitions
# stateless

iface eth0 {
# prefix delegation
    pd

# ask for options
# option dns-server
# option domain
#    option ntp-server
#    option time-zone
#    option sip-server
#    option sip-domain
#    option nis-server
#    option nis-domain
#    option nis+-server
#    option nis+-domain
}
&lt;/pre&gt;&lt;/div&gt;


&lt;h2 id="configuration-du-firewall"&gt;Configuration du firewall&lt;/h2&gt;
&lt;p&gt;Si vous avez un firewall sur votre dedibox, assurez vous que les paquets UDP sur le port 546 sont bien autorisés&lt;/p&gt;
&lt;p&gt;&lt;WRAP round alert&gt;
ATTENTION, il s'agit ici du firewall IPv6, donc ip6table si c'est celui que vous utilisez, à ne pas confondre avec son cousin iptables qui ne travaille qu'en IPv4
&lt;/WRAP&gt;&lt;/p&gt;
&lt;p&gt;Par exemple :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;root@localhost:~#&lt;/span&gt; ip6tables -A INPUT -p udp --dport &lt;span class="m"&gt;546&lt;/span&gt; -j ACCEPT
&lt;/pre&gt;&lt;/div&gt;


&lt;h2 id="lancement-de-dibbler-et-lecture-des-logs"&gt;Lancement de dibbler (et lecture des logs)&lt;/h2&gt;
&lt;p&gt;Lancer dibbler&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;root@localhost:~#&lt;/span&gt; service dibller-client start
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Puis jetez un oeil dans le fichier de log &lt;code&gt;/var/log/dibbler/dibbler-client.log&lt;/code&gt; qui devrait ressembler à ceci :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Notice&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Dibbler&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;portable&lt;/span&gt; &lt;span class="n"&gt;DHCPv6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="mf"&gt;0.8.2&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CLIENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Linux&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Notice&lt;/span&gt;    &lt;span class="n"&gt;My&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;28896&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;stored&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;dibbler&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Notice&lt;/span&gt;    &lt;span class="n"&gt;Detected&lt;/span&gt; &lt;span class="n"&gt;iface&lt;/span&gt; &lt;span class="n"&gt;eth1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MAC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nl"&gt;aa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;bb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;cc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;ee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ff&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Notice&lt;/span&gt;    &lt;span class="n"&gt;Detected&lt;/span&gt; &lt;span class="n"&gt;iface&lt;/span&gt; &lt;span class="n"&gt;eth0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MAC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nl"&gt;aa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;bb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;cc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;ee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ff&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Notice&lt;/span&gt;    &lt;span class="n"&gt;Detected&lt;/span&gt; &lt;span class="n"&gt;iface&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MAC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Notice&lt;/span&gt;    &lt;span class="n"&gt;Parsing&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;dibbler&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;Prefix&lt;/span&gt; &lt;span class="n"&gt;delegation&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;Parsing&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;dibbler&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt; &lt;span class="n"&gt;done&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;specified&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;dibbler&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Info&lt;/span&gt;      &lt;span class="n"&gt;Interface&lt;/span&gt; &lt;span class="n"&gt;eth0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;configuation&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;been&lt;/span&gt; &lt;span class="n"&gt;loaded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;DUID&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt; &lt;span class="n"&gt;was&lt;/span&gt; &lt;span class="n"&gt;loaded&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;duid&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Info&lt;/span&gt;      &lt;span class="n"&gt;My&lt;/span&gt; &lt;span class="n"&gt;DUID&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Info&lt;/span&gt;      &lt;span class="n"&gt;Loading&lt;/span&gt; &lt;span class="n"&gt;old&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;AddrMgr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="n"&gt;built&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;routines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Info&lt;/span&gt;      &lt;span class="n"&gt;DB&lt;/span&gt; &lt;span class="nl"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1378498106&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1378498706&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;old&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;Loaded&lt;/span&gt; &lt;span class="n"&gt;PD&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="nl"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iaid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iface&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;Parsed&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nl"&gt;a01&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;xxxx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;xxxx&lt;/span&gt;&lt;span class="o"&gt;::/&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;valid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1378498106&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;Parsed&lt;/span&gt; &lt;span class="n"&gt;PD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pdid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt; &lt;span class="n"&gt;loaded&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;disk&lt;/span&gt; &lt;span class="n"&gt;successfuly&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;ia&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ta&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;Bind&lt;/span&gt; &lt;span class="n"&gt;reuse&lt;/span&gt; &lt;span class="n"&gt;enabled&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multiple&lt;/span&gt; &lt;span class="n"&gt;instances&lt;/span&gt; &lt;span class="n"&gt;allowed&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Notice&lt;/span&gt;    &lt;span class="n"&gt;Creating&lt;/span&gt; &lt;span class="n"&gt;control&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Notice&lt;/span&gt;    &lt;span class="n"&gt;Creating&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;fe80&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="mo"&gt;0000&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;0000&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;0000&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="n"&gt;a4f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;eth0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;Initialising&lt;/span&gt; &lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="n"&gt;detection&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nl"&gt;interfaces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;eth0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; 
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Notice&lt;/span&gt;    &lt;span class="n"&gt;CONFIRM&lt;/span&gt; &lt;span class="n"&gt;support&lt;/span&gt; &lt;span class="n"&gt;compiled&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Info&lt;/span&gt;      &lt;span class="n"&gt;Creating&lt;/span&gt; &lt;span class="n"&gt;SOLICIT&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;IA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;TA&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;PD&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;eth0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;Sending&lt;/span&gt; &lt;span class="n"&gt;SOLICIT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;eth0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;multicast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;Sleeping&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;Received&lt;/span&gt; &lt;span class="mi"&gt;133&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;interface&lt;/span&gt; &lt;span class="n"&gt;eth0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;fe80&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="mf"&gt;6e41&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="nl"&gt;aff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;fec7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;72ff&lt;/span&gt;&lt;span class="p"&gt;.).&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Info&lt;/span&gt;      &lt;span class="n"&gt;Received&lt;/span&gt; &lt;span class="n"&gt;ADVERTISE&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;eth0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;TransID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mh"&gt;0xecc4ba&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="nl"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Info&lt;/span&gt;      &lt;span class="n"&gt;ADVERTISE&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;prefrence&lt;/span&gt; &lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt; &lt;span class="n"&gt;received&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;so&lt;/span&gt; &lt;span class="n"&gt;wait&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt; &lt;span class="n"&gt;possible&lt;/span&gt; &lt;span class="n"&gt;ADVERTISE&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;skipped&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Info&lt;/span&gt;      &lt;span class="n"&gt;Creating&lt;/span&gt; &lt;span class="n"&gt;REQUEST&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Backup&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;contains&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;Advertise&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;Server&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;preference&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.[&lt;/span&gt;&lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;Authentication&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;including&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;Sending&lt;/span&gt; &lt;span class="n"&gt;REQUEST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;eth0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;multicast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;Not&lt;/span&gt; &lt;span class="n"&gt;executing&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="n"&gt;script&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Notify&lt;/span&gt; &lt;span class="n"&gt;script&lt;/span&gt; &lt;span class="n"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;Sleeping&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;Received&lt;/span&gt; &lt;span class="mi"&gt;127&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;interface&lt;/span&gt; &lt;span class="n"&gt;eth0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;fe80&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="mf"&gt;6e41&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="nl"&gt;aff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;fec7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;xxxx&lt;/span&gt;&lt;span class="p"&gt;.).&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Info&lt;/span&gt;      &lt;span class="n"&gt;Received&lt;/span&gt; &lt;span class="n"&gt;REPLY&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;eth0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;TransID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mh"&gt;0xdcc722&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="nl"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Warning&lt;/span&gt;   &lt;span class="nl"&gt;PD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Prefix&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nl"&gt;a01&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;0000&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;0000&lt;/span&gt;&lt;span class="o"&gt;::/&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;already&lt;/span&gt; &lt;span class="n"&gt;assigned&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;PD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Notice&lt;/span&gt;    &lt;span class="nl"&gt;PD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Adding&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nl"&gt;a01&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;0000&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;0000&lt;/span&gt;&lt;span class="o"&gt;::/&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="n"&gt;interfaces&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;split&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;56&lt;/span&gt; &lt;span class="n"&gt;prefixes&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;necessary&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="nl"&gt;PD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Interface&lt;/span&gt; &lt;span class="n"&gt;eth1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;down&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ignoring&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="nl"&gt;PD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Interface&lt;/span&gt; &lt;span class="n"&gt;eth0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;been&lt;/span&gt; &lt;span class="n"&gt;obtained&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;skipping&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="nl"&gt;PD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Interface&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;multicast&lt;/span&gt; &lt;span class="n"&gt;capable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ignoring&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Info&lt;/span&gt;      &lt;span class="nl"&gt;PD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Using&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;suitable&lt;/span&gt; &lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Warning&lt;/span&gt;   &lt;span class="n"&gt;Suitable&lt;/span&gt; &lt;span class="n"&gt;interfaces&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Delegated&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;RENEW&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;sent&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="mi"&gt;1800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;REBIND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;Not&lt;/span&gt; &lt;span class="n"&gt;executing&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="n"&gt;script&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Notify&lt;/span&gt; &lt;span class="n"&gt;script&lt;/span&gt; &lt;span class="n"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;span class="mf"&gt;2013.09.06&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;26&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;Debug&lt;/span&gt;     &lt;span class="n"&gt;Sleeping&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="mi"&gt;1800&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Assurez vous avant toute chose que l'échange s'est bien passé et que votre bloc IPv6 a bien été attribué à votre dedibox.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;  2013.09.06 22:18:26 Client Notice    PD: Adding prefix 2a01:0000:0000::/48 to all interfaces (prefix will be split to /56 prefixes if necessary).
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Ensuite, vous remarquerez que le log contient l'IP du routeur qui vous a répondu. Notez là, vous en aurez besoin plus tard (&lt;em&gt;ce sera votre default gateway&lt;/em&gt;).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;2013.09.06 22:18:26 Client Debug     Received 127 bytes on interface eth0/2 (socket=4, addr=fe80::6e41:6aff:fec7:xxxx.).
&lt;/pre&gt;&lt;/div&gt;


&lt;h1 id="configuration-de-linterface"&gt;Configuration de l'interface&lt;/h1&gt;
&lt;p&gt;Il vous reste ensuite simplement à configurer une IP de votre bloc sur l'interface de votre dedibox. Le plus simple est de prendre la première&lt;sup id="fnref:premiere"&gt;&lt;a class="footnote-ref" href="#fn:premiere" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt;, c'est à dire &lt;code&gt;2a01:0e0b:0000::1&lt;/code&gt; si votre prefix est &lt;code&gt;2a01:0e0b:0000::/48&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ajoutez&lt;/strong&gt; (i.e. APRES la config IPv4) les lignes suivantes à votre fichier &lt;code&gt;/etc/network/interfaces&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;iface eth0 inet6 static
    address 2a01:0e0b:0000::1
    netmask 48
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Veuillez à bien adapter l'adresse à votre cas.
L'adresse est une adresse que vous choisissez dans votre bloc.&lt;/p&gt;
&lt;h1 id="et-pour-ma-default-gateway"&gt;Et pour ma default Gateway ?&lt;/h1&gt;
&lt;h2 id="automatiquement-les-paquets-ra"&gt;Automatiquement - Les paquets RA&lt;/h2&gt;
&lt;p&gt;Les routeurs d'online passent leur temps à arroser le réseau avec l'adresse IPv6 du routeur par lequel votre dedibox doit passer.
Il s'agit de paquet RA.
pour une explication détaillée du fonctionnement : &lt;a href="http://blog.bashy.eu/2011/03/paquet-router-advertisement/"&gt;http://blog.bashy.eu/2011/03/paquet-router-advertisement/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Normalement, donc, votre default gateway se met toute seule en place et vous n'avez rien à faire.
Néanmoins, les vérifications suivantes peuvent s'avérer nécessaires :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Les paquets ICMPv6 doivent arriver à votre machine, donc ne pas être droppés par le firewall&lt;/li&gt;
&lt;li&gt;Les paquets multicast ne doivent pas être droppés.&lt;/li&gt;
&lt;li&gt;La machine doit accepter les paquets RA. Ces variables kernel doivent être à 1 :&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;root@localhost:~#&lt;/span&gt; sysctl -a &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="s1"&gt;&amp;#39;accept_ra =&amp;#39;&lt;/span&gt;
&lt;span class="go"&gt;net.ipv6.conf.all.accept_ra = 1&lt;/span&gt;
&lt;span class="go"&gt;net.ipv6.conf.default.accept_ra = 1&lt;/span&gt;
&lt;span class="go"&gt;net.ipv6.conf.eth0.accept_ra = 1&lt;/span&gt;
&lt;span class="go"&gt;net.ipv6.conf.eth1.accept_ra = 1&lt;/span&gt;
&lt;span class="go"&gt;net.ipv6.conf.lo.accept_ra = 1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Le forwarding doit être désactivé, sinon le noyau est en mode routeur et n'accepte pas les paquest RA. à moins de forcer l'acceptation des paquets RA même avec le forwarding activé en positionnant les variables accept_ra à 2 plutôt qu'
à 1.&lt;sup id="fnref:accept_ra"&gt;&lt;a class="footnote-ref" href="#fn:accept_ra" rel="footnote"&gt;2&lt;/a&gt;&lt;/sup&gt;
C'est probablement le cas si vous avez installé openvpn ou un logiciel de firewalling qui a activé le forward.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lorsque ces conditions sont réunies, cétotomatix&lt;/p&gt;
&lt;h2 id="manuellement-parce-que-ca-ne-marche-pas"&gt;Manuellement parce que ça ne marche pas&lt;/h2&gt;
&lt;p&gt;Si le paragraphe précédent ne vous a pas permis de bénéficier de la configuration automatique, dites vous :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Que vous êtes un boulet, comme moi&lt;/li&gt;
&lt;li&gt;Qu'il y a toujours possibilité de définir manuellement sa défault gateway&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pour se faire, comme on a l'adresse du routeur (souvenez vous, elle est dans les logs de dibbler), il suffit d'ajouter au fichier &lt;code&gt;/etc/network/interfaces&lt;/code&gt; dans la section inet6 une ligne&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;gateway fe80::6e41:6aff:fec7:xxxx
&lt;/pre&gt;&lt;/div&gt;


&lt;h1 id="ya-plus-qua"&gt;Y'a plus qu'à&lt;/h1&gt;
&lt;p&gt;relancez le tout et testez :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;root@localhost:~#&lt;/span&gt; service networking restart
&lt;span class="go"&gt;networking stop/waiting&lt;/span&gt;
&lt;span class="go"&gt;networking start/running&lt;/span&gt;
&lt;span class="gp"&gt;root@localhost:~#&lt;/span&gt; ping6 ipv6.google.com
&lt;span class="go"&gt;PING ipv6.google.com(we-in-x67.1e100.net) 56 data bytes&lt;/span&gt;
&lt;span class="go"&gt;64 bytes from we-in-x67.1e100.net: icmp_seq=1 ttl=55 time=9.80 ms&lt;/span&gt;
&lt;span class="go"&gt;64 bytes from we-in-x67.1e100.net: icmp_seq=2 ttl=55 time=9.83 ms&lt;/span&gt;
&lt;span class="go"&gt;64 bytes from we-in-x67.1e100.net: icmp_seq=3 ttl=55 time=9.74 ms&lt;/span&gt;
&lt;span class="go"&gt;^C&lt;/span&gt;
&lt;span class="go"&gt;--- ipv6.google.com ping statistics ---&lt;/span&gt;
&lt;span class="go"&gt;3 packets transmitted, 3 received, 0% packet loss, time 2002ms&lt;/span&gt;
&lt;span class="go"&gt;rtt min/avg/max/mdev = 9.741/9.793/9.835/0.039 ms&lt;/span&gt;
&lt;span class="gp"&gt;root@localhost:~#&lt;/span&gt; 
&lt;/pre&gt;&lt;/div&gt;


&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:premiere"&gt;
&lt;p&gt;En fait, c'est la seconde, puisque la première est l'adresse 0. Contrairement à l'IPv4, l'IPv6 permet d'utiliser toutes les adresses, de la première (0) à la dernière (ffff)&amp;#160;&lt;a class="footnote-backref" href="#fnref:premiere" rev="footnote" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:accept_ra"&gt;
&lt;p&gt;Voir à ce sujet &lt;a href="http://www.mattb.net.nz/blog/2011/05/12/linux-ignores-ipv6-router-advertisements-when-forwarding-is-enabled/"&gt;http://www.mattb.net.nz/blog/2011/05/12/linux-ignores-ipv6-router-advertisements-when-forwarding-is-enabled/&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:accept_ra" rev="footnote" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</summary><category term="dedibox"></category><category term="ipv6"></category><category term="linux"></category></entry><entry><title>Enfin, un blog !</title><link href="https://blog.blaisot.org/premier-post.html" rel="alternate"></link><published>2013-09-07T14:25:00+02:00</published><updated>2013-09-07T14:25:00+02:00</updated><author><name>sblaisot</name></author><id>tag:blog.blaisot.org,2013-09-07:premier-post.html</id><summary type="html">&lt;p&gt;Ca y est, me voici l'heureux propriétaire d'un blog. J'ai une maison sur internet.&lt;/p&gt;
&lt;p&gt;Je ne sais pas encore bien ce que je vais y mettre, surement de tout et de rien, de l'informatique, bien sûr, des humeurs, de l'info aussi.&lt;/p&gt;
&lt;p&gt;La fréquence de post sera forcément irrégulière, suivant les envies.&lt;/p&gt;
&lt;p&gt;Mais au moins, j'aurai un lieu où publier ce que j'aurai envie de partager.&lt;/p&gt;
&lt;p&gt;EDIT : Commentaire de madame :
"Tu va raconter ta vie ? Tu va mettre des recettes de cuisine ? Des photos de chat ? Non ? alors ça sert à rien..."&lt;/p&gt;
&lt;p&gt;S.B.&lt;/p&gt;</summary><category term="blog"></category></entry></feed>