Monter son serveur DNS over HTTPS

Date de publication: 25/03/2020

Bonjour à toutes et à tous, Étant passionné de sécurité et de vie privée numérique, les nouveaux protocoles et les nouvelles technologies me fascinent. Cela fait maintenant quelques mois que je voyais des articles sur le DoH (DNS over HTTPS). En ces temps de confinement, l’occasion est parfaite pour m’y intéresser de plus près. Si vous avez commencé à lire cet article, c’est que vous savez sûrement déjà ce qu’est le protocole DNS et le protocole HTTPS. Je ne vais donc pas faire un cours sur ces deux protocoles qui règnent en grande partie sur Internet :)

Le protocole DoH est, contrairement au protocole DoT (DNS over TLS), un protocole d’encapsulation. La principale différence entre le DoH et le DoT est que le DoT implémente une gestion du chiffrement par dessus DNS, alors que le DoH est un procédé d’encapsulation mémé à un nouveau formatage du protocole DNS. En effet, dans une trame DoH, les données ne sont pas sous la même forme que DNS.

Les données sont alors transmises au format JSON. Pour les personnes voulant creuser le sujet, voici un lien vers une excellente documentation traitant du sujet.

Je pense écrire un article sur la controverse du DoH. En effet, le DoH amène son lot de nouveautés et surtout son lot de protections. En passant les requêtes DNS sous HTTPS, il est donc plus difficile d’en inspecter le contenu. Pour les enthousiastes comme vous et moi, le DoH est une couche de confidentialité supplémentaire dans nos vies virtuelles. Maintenant que je vous ai convaincu que le DoH était un excellent protocole (Non ? Comment ça !?), passons au choses sérieuses: Installons notre propre serveur DoH ! Vous êtes prêts ? C’est parti !

Prérequis

Architecture

Un beau diagramme vaut mieux que 1000 mots. Voici comment notre installation va être mise en place:

Installation

Commencez par mettre à jours votre machine

sudo apt update -y && sudo apt upgrade -y

Installation de dnscrypt

J’ai choisi d’utiliser dnscrypt pour son interfaçage intuitif et sa grande variété de serveur DNS fournis par la communauté. Ajoutons la PPA de dnscrypt puis lançons son installation.

sudo add-apt-repository ppa:shevchuk/dnscrypt-proxy
sudo apt install dnscrypt-proxy -y

Une fois installé, dnscrypt se lancera automatiquement lors du boot. Afin de garder se tutoriel simple, je vais utiliser Cloudflare en tant que fournisseur DNS. Si cela ne vous convient pas (ce que je comprends amplement), vous avez le choix entre des centaines d’autres serveurs sur le site de dnscrypt. Afin de le configurer, il suffit de modifier le fichier /etc/dnscrypt-proxy/dnscrypt-proxy.toml Cherchez la section “General” et changez la valeur de la variable server_names.

server_names = ['cloudflare']

Une fois modifié, redémarrons le service.

sudo systemctl restart dnscrypt-proxy

Par défaut, dnscrypt utilise la librairie socket de systemd afin d’écouter sur 127.0.2.1:53 Nous en avons fini avec dnscrypt !

Installation du serveur DNS-over-HTTPS

La manière la plus simple d’installer le serveur DoH est de l’installer à partir du paquet .deb disponible à cette adresse. (Ce .deb peut être aussi installé sur n’importe quelle machine basée sous Debian. Par soucis de simplicité, je vous ai demandé en début d’article une machine Ubuntu car je n’ai pas testé ce .deb sous Debian.) Une fois téléchargé, il vous suffit de l’installer avec la commande suivante.

sudo dpkg -i doh-server_2.0.1_amd64.deb

Si vous préférez le compiler vous-même, vous pouvez suivre le guide fourni dans le repo GitHub. En ce qui concerne la configuration, cela se passe dans le fichier /etc/dns-over-https/doh-server.conf Il vous suffit de changer la valeur des variables listen & upstream afin de coordonner avec notre architecture.

# HTTP listen port
listen = [
    "127.0.0.1:8053",
    "[::1]:8053",
]
# Upstream DNS resolver
# If multiple servers are specified, a random one will be chosen each time.
upstream = [
    "127.0.2.1:53",
]

Cette configuration va permettre de spécifier au serveur DoH d’utiliser dnscrypt pour nos requêtes DNS. Une fois terminé, il nous suffit de redémarrer le service.

sudo systemctl restart doh-server

Installation de Nginx

Nous allons ajouter la PPA de Nginx qui contient sa dernière version. Cette dernière supporte le TLS 1.3, version recommandée d’utilisation à ce jour.

sudo add-apt-repository ppa:ondrej/nginx
sudo apt install nginx-full

Pour la configuration, il vous suffit de créer le fichier /etc/nginx/sites-available/dns-over-https et d’y mettre le contenu suivant.

upstream dns-backend {
    server 127.0.0.1:8053;
}
server {
        listen 80;
        server_name dns.example.com;
        root /var/www/html/dns;
        access_log /var/log/nginx/dns.access.log;
         location /dns-query {
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_set_header X-NginX-Proxy true;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_redirect off;
                proxy_set_header        X-Forwarded-Proto $scheme;
                proxy_read_timeout 86400;
                proxy_pass http://dns-backend/dns-query ;
        }
}

La seule chose à changer est la valeur de la variable server_name. Ici, vous devez spécifier le nom de domaine attribué à votre serveur DoH. Faites ensuite un lien symbolique vers la configuration que nous allons activer. Demandez à Nginx de vérifier que la configuration fonctionne et rechargez-le.

sudo ln -s /etc/nginx/sites-available/dns-over-https /etc/nginx/sites-enabled/dns-over-https
sudo nginx -t
sudo systemctl reload nginx

Désormais, Nginx est configuré de telle sorte à ce que tous les paquets HTTPS reçus seront redirigés vers votre serveur DoH.

Génération de certificat HTTPS avec Let’s Encrypt

Qu’est ce que le HTTP sans S ? Pour être franc, un véritable cauchemar… Nous allons donc devoir fournir à notre Nginx son propre certificat HTTPS tout beau, tout fraîchement généré par Let’s Encrypt. Tout d’abord, nous devons installer certbot, qui nous permettra de configurer notre Nginx de manière totalement automatique.

sudo add-apt-repository ppa:certbot/certbot
sudo apt install python-certbot-nginx

Il ne nous reste plus qu’à demander gentiment à Let’s Encrypt de nous donner un certificat HTTPS, et certbot se chargera de l’installation et de la configuration de Nginx. Veuillez remplacer “dns.example.com” par votre propre domaine.

sudo certbot --nginx -d dns.example.com

Si c’est la première fois que vous exécutez certbot, vous serez invité à saisir une adresse e-mail et à accepter les conditions d’utilisation. Après cela, certbot communiquera avec le serveur Let’s Encrypt, puis lancera un défi pour vérifier que vous contrôlez le domaine pour lequel vous demandez un certificat.

    Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
    -------------------------------------------------------------------------------
    1: No redirect - Make no further changes to the webserver configuration.
    2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
    new sites, or if you're confident your site works on HTTPS. You can undo this
    change by editing your web server's configuration.
    -------------------------------------------------------------------------------
    Select the appropriate number [1-2] then [enter] (press 'c' to cancel):

Hardening SSL

Certbot est livré avec des valeurs par défaut SSL “pas mal”, mais elles n’ont pas été mises à jour depuis un certain temps. Cette configuration conserve le support de TLS 1.0 qui est obsolète depuis quelques années. Aucun appareil ne devrait l’utiliser. De plus, la liste de chiffrement choisie contient des cyphers faibles. En tant que bon nerd, nous nous devons de faire les choses bien. Pour cela, voici un fichier de configuration améliorant les valeurs par défaut de Certbot. Il suffit d’éditer le fichier /etc/letsencrypt/options-ssl-nginx.conf et d’y mettre le contenu suivant.

# This file contains important security parameters. If you modify this file
# manually, Certbot will be unable to automatically provide future security
# updates. Instead, Certbot will print and log an error message with a path to
# the up-to-date file that you will need to refer to when manually updating
# this file.
ssl_session_cache shared:le_nginx_SSL:1m;
ssl_session_timeout 1440m;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
# Enable modern TLS cipher suites
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
# The order of cipher suites matters
ssl_prefer_server_ciphers on;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Ensuite, rechargeons Nginx.

sudo systemctl reload nginx

Conclusion

Bravo !  Vous êtes maintenant l’heureux détenteur d’un serveur DoH ! Il vous suffit de pointer votre navigateur internet préféré vers l’adresse suivante, en veillant à bien avoir activé le DoH sur ce dernier.

https://dns.example.com/dns-query

Si vous avez aimé cet article, n’hésitez pas à me le dire, ça fait toujours très plaisir :) Je tiens à préciser que cet article est volontairement en grande partie repris de l’excellent site d’Antoine Aflalo qui fait du super travail ! N’hésitez pas à visiter son site web qui vaux le coup d’œil :) À très bientôt pour un nouvel article !