README.md 25.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Installation et configuration d'un résolveur DoT et DoH public
==============================================================

DNS over TLS (DoT) et DNS over HTTPS (DoH) sont deux protocoles standardisés
par l'IETF dans les [RFC 7858](https://www.rfc-editor.org/rfc/rfc7858) et
[RFC 8484](https://www.rfc-editor.org/rfc/rfc8484) respectivement. Ces deux
protocoles ont pour but de sécuriser les requêtes DNS entre un client et le
résolveur. Ces deux protocoles sont en fait une encapsulation du protocole DNS
dans une session TLS pour DoT ou HTTPS pour DoH.

Pour plus d'informations sur DoH, une présentation a été réalisée lors de [la
journée du Conseil Scientifique
2019](https://www.afnic.fr/fr/l-afnic-en-bref/actualites/actualites-generales/12284/show/jcsa19-retour-sur-l-edition-2019-de-la-journee-du-conseil-scientifique-de-l-afnic-1.html).

Le but de ce document est de décrire comment installer et configurer son propre
résolveur DoT et DoH accessible depuis Internet.

Il existe de nombreux logiciels de résolution DNS. Cependant peu, voire aucun,
ne supportent actuellement nativement et de manière stable les protocoles DoT
et DoH. Cela évolue néanmoins, les éditeurs y travaillent. C'est pour cela
qu'il a été choisi de décrire cette procédure en utilisant
[dnsdist](https://dnsdist.org/) et
[unbound](https://nlnetlabs.nl/projects/unbound/about/). `dnsdist` est un
frontal DNS qui supporte DoT et DoH. En tant que frontal il doit être configuré
pour savoir vers quel résolveur DNS faire suivre les requêtes entrantes.
`unbound` sera ce résolveur.

Ce document suppose que vous disposez des droits administrateurs sur la machine
où vous souhaitez installer le résolveur DoT/DoH. Il est tout à fait possible
d'utiliser une machine locale (serveur, Raspberry Pi) ou un hébergement
externalisé. Ce tutoriel a été réalisé avec un serveur dédié virtuel et le
système d'exploitation Debian 10.

Alexandre's avatar
Alexandre committed
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
---

* [Prérequis](#prérequis)
* [Partie I - Résolveur](#partie-i-résolveur)
    * [Installation](#installation)
    * [Configuration](#configuration)
* [Partie II - Frontal DNS](#partie-ii-frontal-dns)
    * [Installation](#installation-1)
    * [Configuration](#configuration-1)
    * [Utilisation de la console dnsdist](#utilisation-de-la-console-dnsdist)
* [Partie III - Gestion des certificats](#partie-iii-gestion-des-certificats)
    * [Renouvellement des certificats](#renouvellement-des-certificats)
        * [Automatisation avec cron](#automatisation-avec-cron)
        * [Automatisation avec un timer systemd](#automatisation-avec-un-timer-systemd)
    * [Remarques](#remarques)
* [Partie IV - Testez votre résolveur avec l'outil Homer](#partie-iv-testez-votre-résolveur-avec-loutil-homer)
* [Partie V - Utilisez votre résolveur](#partie-v-utilisez-votre-résolveur)

---

Alexandre's avatar
Alexandre committed
54
## Prérequis
55
56
57
58
59
60
61
62
63
64
65

Assurez vous que les ports 853 (DoT), 443 (DoH) et 80 (challenge Let's encrypt)
sont bien ouverts sur votre machine.

Dans le cadre de la mise en place d'un résolveur public, vous possédez un nom
de domaine auquel sont associés les enregistrement `A` et `AAAA` éventuels
correspondant à l'adresse IP sur laquelle sera installé le résolveur DoT/DoH.


La solution technique retenue ici pour le résolveur DoT/DoH est composée d'un
frontal dnsdist qui assure la terminaison des sessions TLS et HTTPS et transmet
Alexandre's avatar
Alexandre committed
66
les requêtes vers un résolveur DNS unbound installé en local sur la machine.
67

Alexandre's avatar
Alexandre committed
68
# Partie I - Résolveur
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

Commençons par installer et configurer le résolveur DNS. Il existe plusieurs
logiciels pour faire de la résolution comme [BIND 9](https://www.isc.org/bind),
[Knot Resolver](https://www.knot-resolver.cz) ou encore
[Unbound](https://nlnetlabs.nl/projects/unbound/about/). Nous avons choisi
d'utiliser Unbound et cette partie documente comment installer et configuer ce
résolveur.

### Installation

En règle général Unbound est disponible dans les dépôts des distributions.
Donc il suffit de l'installer depuis le gestionnaire de paquet de votre
machine.

```
$ sudo apt-get install unbound
```

### Configuration

Maintenant que Unbound est installé, il ne reste plus qu'à le configurer avant
de démarrer le service.

Il s'agit du résolveur DNS, celui ci n'est accessible que depuis la machine
locale via le port 53 (il est tout à fait possible de modifier cette valeur).

Pour cela il est nécessaire de modifier le fichier de configuration par défaut
`/etc/unbound/unbound.conf`. Il est tout à fait possible de sauvegarder la
configuration par défaut :

```
$ sudo cp /etc/unbound/unbound.conf /etc/unbound/unbound.conf.orig
```

Puis modifier le fichier avec le contenu suivant :

```
server:
    # ne rien enregistrer dans les journaux hormis les erreurs
    verbosity: 0

    # n'écouter que sur l'interface locale en IPv4
    # unbound nécessite d'être relancé si modifié
    interface: 127.0.0.1

    port: 53

116
117
    # refuser tout le monde sauf les connexions locales (pas forcément
    # nécessaire vu que le serveur n'écoute que sur la boucle locale en IPv4)
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
    access-control: 0.0.0.0/0 refuse
    access-control: 127.0.0.1/32 allow

    # par défaut, unbound ne log pas les requêtes ni les réponses
    # on peut le rappeler au cas où
    log-queries: no
    log-replies: no

    # imposer la QNAME minimisation (RFC 7816)
    qname-minimisation: yes
    # même si le serveur faisant autorité ne le veut pas
    #   après discussion, il est possible que cette option ne soit
    #   pas recommandée dans le cadre d'un résolveur ouvert
    qname-minimisation-strict: yes
```

Enregistrer le contenu de ce fichier dans `/etc/unbound/unbound.conf`. Il est
possible de vérifier la validité du fichier de configuration avec la commande
suivante :

```
$ unbound-checkconf /etc/unbound/unbound.conf
unbound-checkconf: no errors in /etc/unbound/unbound.conf
```

_Remarque: il est possible que les utilitaires `unbound` et `unbound-checkconf`
soient dans le dossier `/usr/sbin/` et que ce dossier ne soit pas dans le
`PATH`, pour l'y ajouter utilisez la commande suivante :_

```
export PATH=$PATH:/usr/sbin
```

Toutes les règles disponibles sont détaillées dans le manuel `man 5
unbound.conf` ou [dans le manuel en
ligne](https://nlnetlabs.nl/documentation/unbound/unbound.conf/).

Enfin il ne reste plus qu'à démarrer le résolveur.

```
$ sudo systemctl start unbound.service
```

Il est possible de s'assurer que tout fonctionne bien à l'aide de la commande
`dig` disponible dans le paquet `bind9-dnsutils` ou `dnsutils`. Pour cela il
suffit de spécifier l'adresse de notre résolveur, ici `127.0.0.1` ou `::1` et
d'effectuer une requête DNS. Ici on demande à Unbound de récupérer
l'enregistrement `AAAA` associé au nom de domaine `afnic.fr`.

```
$ sudo apt-get install bind9-dnsutils # ou dnsutils selon les distributions
```

```
$ dig @127.0.0.1 AAAA afnic.fr
; <<>> DiG 9.16.1-Ubuntu <<>> @127.0.0.1 AAAA afnic.fr
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35856
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;afnic.fr.                      IN      AAAA

;; ANSWER SECTION:
afnic.fr.               600     IN      AAAA    2001:67c:2218:302::51:231

;; Query time: 152 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Sep 28 10:16:00 UTC 2020
;; MSG SIZE  rcvd: 65
```

Une réponse est bien renvoyée. Le résolveur fonctionne. Il est possible de
195
s'assurer que tout est opérationnel en IPv4, et en utilisant UDP et TCP.
196
197
198
199
200
201
202
203
204
205

```
$ dig +notcp @127.0.0.1 AAAA afnic.fr  # connexion UDP en IPv4 au résolveur
$ dig +tcp @127.0.0.1 AAAA afnic.fr    # connexion TCP en IPv4 au résolveur
```

À ce stade, un résolveur Unbound est configuré en local et écoute sur le port
`53`. Il peut donc être utilisé pour résoudre toutes les requêtes en provenance
de la machine.

Alexandre's avatar
Alexandre committed
206
# Partie II - Frontal DNS
207
208
209

Cette section s'attarde sur l'installation et la configuration d'un frontal
DoT/DoH qui transmettra les requêtes DNS à un résolveur local écoutant sur le
210
port 53 de l'interface local `127.0.0.1` (IPv4).
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484

Ici `dnsdist` se trouve être une très bonne solution pour remplir ce rôle.

### Installation

Il est possible que `dnsdist` soit déjà présent dans les dépôts officiels. Vous
pouvez utilisez cette version, il suffit alors de s'assurer que la version de
dnsdist ainsi récupérée supporte bien DoT et DoH :

```
$ sudo apt-get install dnsdist
$ dnsdist --version
dnsdist 1.4.0 (Lua 5.2.4)
Enabled features: ... dns-over-tls(gnutls openssl) dns-over-https(DOH) ...
```

Si les options `dns-over-tls` et `dns-over-https` ne sont pas listées, ou que
vous désiriez utiliser la dernière version de dnsdist,
[PowerDNS](https://www.powerdns.com) qui développpe le logiciel propose et
maintient [ses propres dépôts pour Debian, Raspbian, Ubuntu et
CentOS](https://repo.powerdns.com/).

Ainsi, voici comment installer la dernière version de dnsdist, actuellement
`1.5.0`, tel que défini sur [le site de PowerDNS](https://repo.powerdns.com/)
pour :

* Debian / Ubuntu / Raspbian
```
# récupération du nom de la distribution et de son ID
# ATTENTION: le fichier /etc/os-release peut être différent selon la distribution
export D_NAME=$(. /etc/os-release; echo ${VERSION_CODENAME})
export D_ID=$(. /etc/os-release; echo ${ID})

# ajout du dépôt aux sources
# Debian / Ubuntu
echo "deb [arch=amd64] http://repo.powerdns.com/${D_ID} ${D_NAME}-dnsdist-15 main" | sudo tee /etc/apt/sources.list.d/pdns.list
# Raspbian
echo "deb http://repo.powerdns.com/raspbian ${D_NAME}-dnsdist-15 main" | sudo tee etc/apt/sources.list.d/pdns.list

# gestion de l'étiquette et de la priorité du nouveau dépôt
sudo tee /etc/apt/preferences.d/dnsdist << EOF
Package: dnsdist*
Pin: origin repo.powerdns.com
Pin-Priority: 600
EOF

# ajout de la clé publique de PowerDNS
curl https://repo.powerdns.com/FD380FBB-pub.asc | sudo apt-key add -

# mise à jour des dépôts
sudo apt-get update

# installation de dnsdist
sudo apt-get install dnsdist
```

* CentOS 7
```
yum install epel-release yum-plugin-priorities
curl -o /etc/yum.repos.d/powerdns-dnsdist-15.repo https://repo.powerdns.com/repo-files/centos-dnsdist-15.repo
yum install dnsdist
```

### Configuration

Maintenant que dnsdist est installé, passons à sa configuration. Cela se passe
dans le fichier `/etc/dnsdist/dnsdist.conf`. Ce fichier utilise une syntaxe
très accessible. Pensez à modifier les IPs avec celle de l'interface de votre
machine.

```
-- le résolveur DoT/DoH est public, on accepte tout le monde en IPv4 et IPv6
setACL({'0.0.0.0/0', '[::]/0'})

-- serveur DNS où transférer les requêtes entrantes
newServer({address='127.0.0.1:53', name='Unbound (local)'})

-- configuration de DoT
-- modifier l'IPv4 et l'IPv6 en conséquence
addTLSLocal('198.51.100.19:853', '/etc/dnsdist/dot-server.crt', '/etc/dnsdist/dot-server.key', {minTLSVersion='tls1.2'})
addTLSLocal('[2001:db8::19]:853', '/etc/dnsdist/dot-server.crt', '/etc/dnsdist/dot-server.key', {minTLSVersion='tls1.2'})

-- configuration de DoH
-- modifier l'IPv4 et l'IPv6 en conséquence
addDOHLocal('198.51.100.19:443', '/etc/dnsdist/doh-server.crt', '/etc/dnsdist/doh-server.key', '/', {minTLSVersion='tls1.2'})
addDOHLocal('[2001:db8::19]:443', '/etc/dnsdist/doh-server.crt', '/etc/dnsdist/doh-server.key', '/', {minTLSVersion='tls1.2'})

-- limitation du trafic à 100 requêtes par seconde
-- plus d'info en <https://dnsdist.org/advanced/qpslimits.html>
addAction(MaxQPSIPRule(100), DropAction())
```

L'ensemble des options de configuration est détaillé [sur le site de
dnsdist](https://dnsdist.org/index.html).

Il est possible de vérifier que le fichier de configuration est valide avec la
commande :

```
$ dnsdist --check-config
Configuration '/etc/dnsdist/dnsdist.conf' OK!
```

dnsdist est donc configuré pour écouter sur l'interface publique de la machine
sur les ports 443 (DoH) et 853 (DoT). Toutes les requêtes sont ensuite relayées
à un serveur écoutant le port 53 sur l'interface locale.

Pour l'instant les fichiers `dot-server.crt`, `dot-server.key`,
`doh-server.crt` et `doh-server.key` n'existent pas. Il est nécessaire de les
générer. Cela peut se faire avec `openssl` dans le cas de certificats
auto-signés. Il est aussi possible de passer par une autorité de certification,
ceci est le but de la prochaine partie.

Remarque: attention aux droits des fichiers du certificat et de la clé,
          l'utilisateur ou le groupe `dnsdist` (parfois `_dnsdist`, vérifier le
          contenu du fichier `/etc/group` avec la commande `grep dnsdist
          /etc/group`) doit avoir les droits en lecture dessus
          `sudo chown -R root:dnsdist /etc/dnsdist`


Remarque: par soucis de sécurité les clés ne sont pas lisibles par tout le
          monde
          `sudo chmod 640 /etc/dnsdist/do[th]-server.key`

### Utilisation de la console dnsdist

Remarque: il est possible qu'en déroulant ce tutoriel de manière linéaire, les
          commandes de cette partie échouent car les fichiers avec les
          certificats n'existent pas encore. Pour remédier à ce problème, vous
          pouvez commenter les lignes contenant `addTLSLocal` et `addDOHLocal`
          dans le fichier de configuration, ou bien générer des certificats
          autosignés avec `openssl` ou encore vous référer à la partie suivante
          sur la gestion des certificats, avant de revenir à celle-ci.

Lorsque dnsdist est lancé par sytemd, le programme est lancé en mode
_supervisé_, c'est à dire sans console. Toutefois avoir un accès à [la console
de dnsdist](https://dnsdist.org/guides/console.html) peut s'avérer utile pour
analyser les codes de retour des requêtes DoH par exemple. Pour cela il est
nécessaire de configurer dnsdist pour accepter le rattachement d'une console
cliente au programme.  Cela passe par l'ajout des options suivantes à la
configuration de dnsdist :

```
-- demande à dnsdist d'écouter sur le port 5199 de l'interface locale
controlSocket('127.0.0.1:5199')
-- définition d'une clé d'authentification que devra utiliser le client
setKey('clé générée avec makeKey()')
-- il est aussi possible de restreindre les accès
setConsoleACL({'127.0.0.1/32', '::1'}) -- depuis la machine locale uniquement
```

Afin de générer la clé privée, lancer la commande `makeKey()` dans la console
dnsdist et copier la sortie dans le fichier de configuration :

```
$ sudo dnsdist
> makeKey()
setKey("Oj9sQ+/PtUm7qLCZtRtzl8uWmgRXSKVqjej+YS/iEjc=")
```

Ainsi, lorsque dnsdist tourne, il est tout à fait possible d'accéder à sa
console depuis la machine locale :

```
$ sudo systemctl start dnsdist
$ dnsdist -c 127.0.0.1:5199
> showDOHResponseCodes()

- HTTP/1:

#   Address               200     400     403     500     502     Others
0   198.51.100.19:443       0       0       0       0       0          0
1   [2001:db8::19]:443      0       0       0       0       0          0

- HTTP/2:

#   Address               200     400     403     500     502     Others
0   198.51.100.19:443       0       0       0       0       0          0
1   [2001:db8::19]:443      0       0       0       0       0          0
```

# Partie III - Gestion des certificats

Afin de pouvoir proposer une connexion sécurisée au résolveur, il est
nécessaire de posséder au moins un certificat par service. Il est tout à fait
possible de générer ses propres certificats auto-signés. Cependant pour
augmenter la confiance dans le service proposé, il est intéressant de s'appuyer
sur un tiers de confiance, l'[autorité de
certification](https://fr.wikipedia.org/wiki/Autorit%C3%A9_de_certification).
Nous allons utiliser [Let's Encrypt](https://letsencrypt.org/) comme autorité
de certification. Let's Encrypt propose par ailleurs un petit utilitaire en
ligne de commande [certbot](https://certbot.eff.org) pour générer et gérer ses
certificats.
La génération d'un certificat via cet utilitaire repose sur un challenge que
doit résoudre la machine.

Bien que nous privilégions et recommandons l'utilsation du challenge DNS ;),
nous retenons ici le challenge HTTP. Ce challenge repose sur l'utilisation d'un
serveur web écoutant sur le port 80. Il n'est pas nécessaire d'avoir un tel
serveur installé sur la machine. Dans ce cas, `certbot` se charge de faire
tourner un serveur web temporaire le temps de résoudre le challenge.  Si un
serveur web écoute déjà sur le port `80` comme `apache` ou `nginx`, certbot
peut être configuré pour utiliser ce serveur web. Pour cela référez vous [aux
instructions de certbot](https://certbot.eff.org/instructions).

Nous allons configurer les noms de domaine suivants : `dot-demo.rd.nic.fr` et
`doh-demo.rd.nic.fr`. Les enregistrements suivants sont ajoutés à la zone
`rd.nic.fr.` (pensez à remplacer les IPs avec celles de votre machine) :

```
dot-demo     86400   A       198.51.100.19
             86400   AAAA    2001:db8::19
doh-demo     86400   A       198.51.100.19
             86400   AAAA    2001:db8::19
```

Une fois cette étape réalisée, il ne reste plus qu'à installer certbot et à
demander 2 certificats, un pour chaque service.

```
$ sudo apt-get install certbot
```

Certbot stocke tous les certificats générés dans
`/etc/letsencrypt/archive/nomdedomaine/` et le répertoire
`/etc/letsencrypt/live/nomdedomaine/` contient des liens vers les fichiers du
dossier `archive/nomdedomaine/`. Par défaut tous ces fichiers sont la
propriété de l'utilisateur `root`.  Or nous avons vu que `dnsdist` tourne avec
l'utilisateur `dnsdist` et donc il est nécessaire que cet utilisateur ait la
capacité de lire les certificats.

Pour cela nous allons suivre la procédure suivante :

  1. (re)générer les certificats avec certbot
  2. copier les certificats dans le dossier `/etc/dnsdist/` en utilisant le nom
     utilisé dans la configuration de dnsdist
  3. modifier les droits de ces fichiers
     `sudo chown :dnsdist /etc/dnsdist/do[th]-server.*` (il est possible que le
     nom du groupe diffère, par exemple `_dnsdist`)
  4. relancer dnsdist

Génération d'un certificat pour le nom de domaine `dot-demo.rd.nic.fr` :

```
$ sudo certbot certonly --standalone -d 'dot-demo.rd.nic.fr' -m 'mail@example.com' --no-eff-email
```

- `-m 'mail@example.com'` : permet de renseigner son mail depuis la ligne de
  commande
- `--no-eff-email` : demander à l'autorité de certification de ne pas
  transmettre le mail à l'EFF

Idem pour le nom de domaine `doh-demo.rd.nic.fr` :

```
$ sudo certbot certonly --standalone -d 'doh-demo.rd.nic.fr' -m 'mail@example.com' --no-eff-email
```

Les étapes 2 à 4 peuvent être automatisées dans un script comme celui ci, que
nous avons appelé `deploy-cert.sh` :

```
#!/bin/sh

# script de déploiement des certificats
# lancé par certbot via l'option --deploy-hook /chemin/du/script.sh
# ce script doit être lancé avec les droits root

DOMAIN_DOT="dot-demo.rd.nic.fr"
DOMAIN_DOH="doh-demo.rd.nic.fr"

DNSDIST_GROUP="$(grep dnsdist /etc/group | cut -d ':' -f 1)"

# copie du certificat utilisé pour DoT
Alexandre's avatar
Alexandre committed
485
486
cp /etc/letsencrypt/live/${DOMAIN_DOT}/fullchain.pem /etc/dnsdist/dot-server.crt
cp /etc/letsencrypt/live/${DOMAIN_DOT}/privkey.pem /etc/dnsdist/dot-server.key
487
488

# copie du certificat utilisé pour DoH
Alexandre's avatar
Alexandre committed
489
490
cp /etc/letsencrypt/live/${DOMAIN_DOH}/fullchain.pem /etc/dnsdist/doh-server.crt
cp /etc/letsencrypt/live/${DOMAIN_DOH}/privkey.pem /etc/dnsdist/doh-server.key
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595

# modification des droits
chown root:${DNSDIST_GROUP} /etc/dnsdist/dot-server.crt /etc/dnsdist/dot-server.key
chown root:${DNSDIST_GROUP} /etc/dnsdist/doh-server.crt /etc/dnsdist/doh-server.key
chmod 640 /etc/dnsdist/dot-server.key /etc/dnsdist/doh-server.key

# relancer dnsdist pour prendre en compte les changements
# REMARQUE: il est aussi possible d'utiliser la console dnsdist pour recharger
#           les certificats, avec l'option reloadAllCertificates() :
#
#             $ dnsdist -c 127.0.0.1:5199
#             > reloadAllCertificates()
#
#           et en une ligne :
#
#             $ dnsdist -c 127.0.0.1:5199 -e 'reloadAllCertificates()'
#
#           cela nécessite que dnsdist soit configuré de sorte à ce que la
#           console soit accessible
systemctl restart dnsdist
```

Ainsi suite à la génération des certificats, il ne reste plus qu'à lancer ce
script :

```
$ sudo ./deploy-cert.sh
```

## Renouvellement des certificats

Les certificats générés par Let's Encrypt ne sont valable que 90 jours. Il
convient de penser à préparer leur renouvellement. Le script `deploy-hook.sh`
s'avère ici très utile pour automatiser le déploiement des certificats, et cela
grâce à l'option `--deploy-hook` de l'utilitaire certbot.

```
$ sudo certbot renew --deploy-hook "/path/to/deploy-cert.sh"
```

Le renouvellement d'un certificat n'a lieu que dans les 30 jours avant son
expiration. Ainsi nous choisissons d'automatiser la demande de renouvellement
toutes les semaines, afin d'être de palier à d'éventuels problèmes (machine qui
redémarre, autorité de certification en panne au moment de la demande...).

### Automatisation avec cron

Il est tout à fait possible d'automatiser cette commande dans une tâche
de type `cron` en ajoutant la ligne suivante à crontab (`sudo crontab -e`) :

```
# se lance toutes les semaines le lundi
0 0 * * 1 certbot renew --deploy-hook "/path/to/deploy-cert.sh"
```

### Automatisation avec un timer systemd

Une autre approche est d'utiliser `systemd` pour automatiser le renouvellement
des certificats. Il s'avère que sur la machine utilisée, `certbot` installe
deux fichiers `systemd` :

- `/lib/systemd/system/certbot.service` : l'unité qui contient la commande à
  lancer pour le renouvellement
- `/lib/systemd/system/certbot.timer` : un minuteur associé au service (ils
  portent le même nom)

Il est alors possible de substituer certaines règles en créant les même
fichiers dans `/etc/systemd/system`. Dans ce cas, systemd retiendra les valeurs
définies dans ces fichiers.

```
$ cat /etc/systemd/system/certbot.service
[Unit]
Description=Certbot renew

[Service]
ExecStart=/usr/bin/certbot renew --deploy-hook "/etc/certbot/deploy-cert.sh"
```

```
$ cat /etc/systemd/system/certbot.timer
[Unit]
Description=Run certbot renew monthly

[Timer]
OnCalendar=weekly
Persistent=true

[Install]
WantedBy=timers.target
```

Une fois les fichiers créés, il reste à recharger ces règles dans systemd :

```
$ sudo systemctl daemon-reload
```

Il est alors possible de vérifier les journaux pour s'assurer du bon
renouvellement :

```
$ journalctl -u certbot.service
```

Alexandre's avatar
Alexandre committed
596
### Remarques
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719

Si vous avez un déjà un programme qui écoute sur le port 80, il est tout à fait
possible de demander à certbot de l'arrêter avant de procéder au renouvellement
puis de le redémarrer avec les options `--pre-hook "systemctl stop program"` et
l'option `--post-hook "systemctl start program"`.

```
$ sudo certbot renew --pre-hook "systemctl stop apache2" --post-hook "systemctl start apache2" --deploy-hook "/path/to/deploy-cert.sh"
```

# Partie IV - Testez votre résolveur avec l'outil Homer

Pour s'assurer que le résolveur fonctionne de manière nominal, il est possible
d'utiliser Homer.

Homer est un outil développé par l'Afnic, qui permet de tester et débugger un
résolveur DoT/DoH en ligne de commande.

Homer est un logiciel libre et le code est disponible [sur la forge logicielle
Framagit](https://framagit.org/bortzmeyer/homer).

L'outil nécessite python3, et certains modules associés :

```
$ sudo apt-get install python3 python3-pycurl python3-dnspython python3-openssl python3-netaddr
```

Il ne reste plus qu'à récupérer Homer et à le lancer.

```
$ git clone https://framagit.org/bortzmeyer/homer
$ cd homer
$ ./homer.py https://doh-demo.rd.nic.fr afnic.fr
id 0
opcode QUERY
rcode NOERROR
flags QR RD RA
edns 0
payload 4096
option ECS ::/0 scope/0
;QUESTION
afnic.fr. IN AAAA
;ANSWER
afnic.fr. 600 IN AAAA 2001:67c:2218:302::51:231
;AUTHORITY
;ADDITIONAL

Total elapsed time: 0.07 seconds (65.68 ms/request)
```

```
$ ./homer.py --dot dot-demo.rd.nic.fr framagit.org
id 59643
opcode QUERY
rcode NOERROR
flags QR RD RA
edns 0
payload 4096
;QUESTION
framagit.org. IN AAAA
;ANSWER
framagit.org. 2730 IN AAAA 2a01:4f8:231:4c99::75
;AUTHORITY
;ADDITIONAL

Total elapsed time: 0.01 seconds (7.99 ms/request)
```

Homer peut aussi être utilisé pour tester la bonne configuration du résolveur :

```
$ ./homer.py --check --dot dot-demo.rd.nic.fr framasoft.org
OK

$ ./homer.py --check https://doh-demo.rd.nic.fr chatons.org
OK
```

Dans le cas où votre résolveur est mal configuré, Homer s'arrête est affiche
l'erreur rencontrée. Par exemple pour un certificat non configuré :

```
$ ./homer.py --dot 198.51.100.19 framasoft.org
198.51.100.19: Certificate error: "198.51.100.19 is not in the certificate
Could not connect to "198.51.100.19"
```

Il est toutefois possible de demander à Homer de ne pas vérifier le certificat
avec l'option `-k | --insecure` :

```
$ ./homer.py --insecure --dot 198.51.100.19 framasoft.org
id 35430
opcode QUERY
rcode NOERROR
flags QR RD RA
edns 0
payload 4096
option ECS ::/0 scope/0
;QUESTION
framasoft.org. IN AAAA
;ANSWER
framasoft.org. 3600 IN AAAA 2a01:4f8:141:3421::212
;AUTHORITY
;ADDITIONAL

Total elapsed time: 0.04 seconds (41.83 ms/request)
```

# Partie V - Utilisez votre résolveur

Vous voilà désormais en possession d'un résolveur DoT/DoH public.

DoT/DoH est supporté par plusieurs navigateurs :
[Firefox](https://support.mozilla.org/en-US/kb/firefox-dns-over-https),
[Chrome](https://blog.chromium.org/2020/05/a-safer-and-more-private-browsing-DoH.html),
Edge et [Opera](https://blogs.opera.com/desktop/2019/10/opera-65-beta/) mais
également par plusieurs systèmes d'exploitation :
[Android](https://android-developers.googleblog.com/2018/04/dns-over-tls-support-in-android-p.html)
et prochainement iOS / MacOS et Windows 10.

Les indications pour configurer son navigateur peuvent varier. Nous vous
laissons le soin de vous renseigner selon les outils que vous utilisez.