DoT = DNS over TLS (lire).
DoH = DNS over HTTPS (lire).
Explication en vidéo 1. Explication vidéo 2.
Dans les deux cas, on chiffre et on authentifie le trafic DNS entre une machine (stub resolver) / un serveur récursif local (genre Pi-hole) et un serveur récursif sur Internet.
Le but ? Si l'on utilise un serveur DNS récursif (resolver) différent de celui de son FAI afin d'échapper à différents types de filtrage (judiciaire, administratif, technique, etc.), le FAI peut voir et censurer ce trafic DNS. Donc on le chiffre et on l'authentifie (je ne parle pas d'authentifier la donnée, ça c'est le boulot de DNSSEC). (Évidemment, le FAI pourra bloquer l'adresse IP d'un récursif DoT / DoH ou en fonction du SNI… et on passera alors à Encrypted SNI, etc., etc.)
Un stub resolver (la libc de GNU/Linux, par exemple) ne sait pas utiliser DoT / DoH.
Certains logiciels savent les utiliser (Firefox, par ex.), mais alors seuls eux en bénéficient, le trafic DNS des autres logiciels reste en clair.
Comment utiliser DoT ou DoH pour tous les logiciels d'une machine ? En demandant au stub resolver (la libc de GNU/Linux) de les transférer à un intermédiaire qui, d'un côté, cause DNS, et de l'autre, DoT / DoH. Mais lequel ? (Le transfert s'effectue en mettant l'adresse IP de l'intermédiaire, y compris ::1 / 127.0.0.1 dans /etc/resolv.conf.)
systemd-resolved implémente DoT mais je souhaite éviter cette pieuvre.
(Ou tout autre serveur DNS récursif installé localement.)
Config' à mettre dans /etc/unbound/unbound.conf.d/forward.conf
(par exemple) :
server:
tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt # magasin des certificats racines, apt install ca-certificates
forward-zone:
name: "."
forward-tls-upstream: yes # activation DoT
forward-addr: 2001:910:800::40@853#ns1.fdn.fr # syntaxe : <IP>@<PORT>#<NOM> (le nom sera comparé avec ceux présentés par le serveur dans son certificat x509)
forward-addr: 2001:910:800::12@853#ns0.fdn.fr
Tout comme tonton Bortz, j'ai d'abord rencontré une erreur dans la vérification du certificat x509 : « error: ssl handshake failed crypto error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed ». openssl s_client
et gnutls-cli
validaient le certificat avec le même magasin de certificats. Puis Unbound est tombé en marche tout seul… Je l'ai réinstallé en supprimant /etc/ounbound et en vérifiant qu'il n'avait rien laissé dans /var, et ça fonctionne encore avec la conf' ci-dessus… Ce n'est pas un problème de Subject / Subjet Alternative Name, ni un problème de certificat intermédiaire non-fourni dans l'échange TLS, ni… J'ai aucune piste sérieuse.
Dans le cadre de tests de charge simulant un usage courant, je voulais que les requêtes DNS de mon système soient transférées à un récursif DNS sans mise en cache local des réponses. Or, Unbound pratique une telle mise en cache.
Tonton Bortz m'a signalé deux options censées désactiver la mise en cache dans Unbound :
rrset-cache-size: 0
msg-cache-size: 0
Mais il n'a pas testé et le manuel d'Unbound ne dit pas explicitement que ça désactive toute forme de cache. Donc ça ne me convient pas : un test doit se faire sur des bases saines.
Bortz m'a parlé de Stubby. Il est empaqueté dans Debian GNU/Linux (paquet du même nom).
Dans /etc/stubby/stubby.yml
, on s'assure d'avoir :
dns_transport_list:
- GETDNS_TRANSPORT_TLS
Et dans « upstream_recursive_servers: », on choisit ou on ajoute ses serveurs. Exemple :
upstream_recursive_servers:
- address_data: 2001:910:800::40
tls_auth_name: "ns1.fdn.fr"
- address_data: 2001:910:800::12
tls_auth_name: "ns0.fdn.fr"
C'est du YAML donc gaffe à bien respecter l'indentation.
On peut aussi pratiquer l'épinglage (le pinning) afin de s'assurer que la clé privée du serveur en face ne changera pas en douce, mais pour moi, il s'agit d'une surenchère inutile.
Je vais en parler pour DoH. Il suffit de remplacer le schéma « https:// » par « tls:// » dans le paramètre « -u » pour transmettre les requêtes DNS via DoT.
Stubby n'implémente pas DoH.
Le projet Adguard (équivalent à uBlock Origin, mais, d'après mes notes de 2016, il était ouvert à la publicité dite acceptable) propose dnsproxy. Source.
Attention : c'est un tout autre logiciel qui est empaqueté sous le même nom dans Debian GNU/Linux.
On télécharge. On décompresse le binaire dans /usr/local/sbin
.
On l'utilise (il est possible de passer un fichier de configuration YAML avec --config-path
) :
sudo dnsproxy -l ::1 -l 127.0.0.1 -p 53 -u https://ns1.fdn.fr/dns-query -u https://ns0.fdn.fr/dns-query --all-servers -b [2001:910:800::40]:53 -b [2001:910:800::12]:53
Écouter sur localhost, en IPv6 et en IPv4, sur le port 53. Transférer les requêtes DNS en alternance aux serveurs ns1.fdn.fr et ns0.fr. Les noms ns(1|0).fdn.fr seront résolus en clair en utilisant les serveurs 2001:910:800::40 et 2001:910:800::12 (qui sont ns(1|0).fdn.fr).
Pour gérer dnsproxy, j'ai créé l'unit systemd suivante dans /etc/systemd/system/dnsproxy.service
:
[Unit]
Description=Proxy DoH
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/sbin/dnsproxy -l ::1 -l 127.0.0.1 -p 53 -u https://ns1.fdn.fr/dns-query -u https://ns0.fdn.fr/dns-query -b [2001:910:800::40]:53 -b [2001:910:800::12]:53
RemainAfterExit=no
Restart=on-failure
RestartSec=10s
[Install]
WantedBy=multi-user.target