Tutoriel creer son resolveur DoT/DoH
This commit is contained in:
712
README.md
Normal file
712
README.md
Normal file
@@ -0,0 +1,712 @@
|
|||||||
|
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.
|
||||||
|
|
||||||
|
# Prérequis
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
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
|
||||||
|
les requêtes vers un résolveur installé en local sur la machine.
|
||||||
|
|
||||||
|
## Partie I - Résolveur
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# refuser tout le monde sauf les connexions locales (IPv4 et IPv6)
|
||||||
|
access-control: 0.0.0.0/0 refuse
|
||||||
|
access-control: 127.0.0.1/32 allow
|
||||||
|
access-control: ::0/0 refuse
|
||||||
|
access-control: ::1 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
|
||||||
|
```
|
||||||
|
|
||||||
|
Il est tout à fait possible de désactiver IPv4 ou IPv6, pour cela ne pas
|
||||||
|
définir l'interface associée et ajouter la règle suivante en fonction :
|
||||||
|
|
||||||
|
```
|
||||||
|
server:
|
||||||
|
do-ip4: no # désactive IPv4
|
||||||
|
do-ip6: no # désactive IPv6
|
||||||
|
```
|
||||||
|
|
||||||
|
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
|
||||||
|
s'assurer que tout est opérationnel en IPv6, et en utilisant UDP et TCP.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ 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
|
||||||
|
$ dig +notcp @::1 AAAA afnic.fr # connexion UDP en IPv6 au résolveur
|
||||||
|
$ dig +tcp @::1 AAAA afnic.fr # connexion TCP en IPv6 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.
|
||||||
|
|
||||||
|
## Partie II - Frontal DNS
|
||||||
|
|
||||||
|
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
|
||||||
|
port 53 de l'interface local `127.0.0.1` (IPv4) et/ou `::1` (IPv6).
|
||||||
|
|
||||||
|
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
|
||||||
|
cp /etc/lestencrypt/live/${DOMAIN_DOT}/fullchain.pem /etc/dnsdist/dot-server.crt
|
||||||
|
cp /etc/lestencrypt/live/${DOMAIN_DOT}/privkey.pem /etc/dnsdist/dot-server.key
|
||||||
|
|
||||||
|
# copie du certificat utilisé pour DoH
|
||||||
|
cp /etc/lestencrypt/live/${DOMAIN_DOH}/fullchain.pem /etc/dnsdist/doh-server.crt
|
||||||
|
cp /etc/lestencrypt/live/${DOMAIN_DOH}/privkey.pem /etc/dnsdist/doh-server.key
|
||||||
|
|
||||||
|
# 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
|
||||||
|
```
|
||||||
|
|
||||||
|
## Remarques
|
||||||
|
|
||||||
|
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.
|
||||||
Reference in New Issue
Block a user