Mise à jour Mars 2020 :

Plus de 3 ans après ma découverte de MITM sur DNS chez Bouygues Telecom, le topic que j’ai lancé sur lafibre.info – suite au conseil d’une personne qui m’a informé qu’un des contributeurs du forum était à l’époque employé de Bouygues – est encore actif. On y apprend que Bouygues Telecom à enfin arrêté avec cette connerie d’interception de requêtes DNS, et aussi SMTP (même si en pratique le port TCP 25 n’est pas utilisé, ça reste dégueulasse). Comme quoi, en gueulant au bon endroit et en étant plusieurs à demander des comptes à une entreprise sur ses pratiques, on peut obtenir des résultats, même à 5 gus dans un garage… C’est une petite victoire, petite parce que le mieux reste encore de laisser tomber les résolveurs qui communiquent en claire et configurer un résolveur DNS-over-HTTP ou DNS-over-TLS, technos qui commencent à se répandre, (son propre résolveur, c’est encore mieux). Mais victoire quand même, parce qu’en pratique, on est encore loin du jour où 100% des résolveurs et des clients/OS utilisés par le grand public utilisent par défaut (sans bidouilles/logiciels tierces) du DoH/DoT à la place d’interroger des résolveurs DNS en clair. Donc cette victoire sera utile pour les gens utilisant des appareils avec des OS ne supportant pas DoH/DoT (vieux OS, notamment mobiles, que les fabricants ne maintiennent pas forcément correctement pour mieux vendre de nouveaux appareils… ), ou qui n’ont aucune idée de ce qu’est un résolveur DNS et comment en choisir et le configurer sur sa machine. Merci à tous les gens qui ont relayé mon article, qui ont fait des tests plus ou moins régulièrement, en publiant les résultats, qui ont contribué de façon constructive au topic sur lafibre.info, et qui ont demandé des comptes à Bouygues. Sans oublier de rester vigilants concernant les atteintes à la neutralité du Net et autres pratqiues dégueulasses, cette victoire se savoure avec une bonne boisson caféinée.

Mise à jour Janvier 2020 :

Bouygues Telecom à complètement viré le support de DNSSEC de ses résolveurs DNS forcés par MITM pour les utilisateurs des forfaits 3G/4G mobiles, d’après les tests effectués par un abonné, qui a publié les résultats sur lafibre.info. Donc il n’y par définition plus d’erreurs relatives à DNSSEC, mais le MITM sur DNS est toujours d’actualité.

Introduction

Pour avoir le support de DANE/TLSA sous Firefox, j’utilise depuis certain temps un addon nommé DNSSEC/TLSA Validator, qui permet en plus de vérifier la validité des signatures DNSSEC (sur les sites qui le supportent) en un coup d’œil. Si la signature est valide, les icônes clé (DNSSEC) et cadenas (HTTPS) apparaissent en vert, si elle erronée, l’icône de la clé apparaît en rouge et cadenas rouge ou gris (HTTP :// à la place du cadenas, en gris. HTTPS, cadenas rouge), comme dans les exemples suivants. Et si le serveur web visité ne supporte pas du tout DNSSEC, les 2 icônes sont en gris.

Un test avec le site dnssec-failed.org, dont la signature DNS est volontairement erronée, pour permettre aux sysadmin de faire des tests en rapport avec DNSSEC, nous donne le résultat attendu.



Jusqu’à là, tout va bien, sauf qu’un jour, en utilisant une connexion 3G de Bouygues Telecom, je me suis rendu compte que j’avais un comportement bizarre au niveau de DNSSEC, pour à peu près tous les noms de domaines, j’ai les deux icônes en rouge (signature erronée) un peu partout, aussi bien sur les sites avec une bonne signature de DNSSEC (debian.org, freebsd.org… ) que des sites ne supportant pas du tout DNSSEC. J’ai décidé de faire les tests plus détaillés.

Voici l’exemple avec debian.org sur une connexion 3G Bouygues :



Voici l’exemple avec debian.org sur une connexion fixe, en utilisant le résolveur DNS de Lorraine Data Network (LDN) pour être de ne pas tomber sur un autre DNS foireux :



J’ai découvert ça il y a plusieurs mois, mais c’est toujours valable, je viens de refaire des tests… De toute évidence, c’est pas normal, du coup, j’ai essayé d’en savoir plus.

Sortez le popcorn et mettez vous bien à l’aise…

Tout d’abord, on fait un dig pour demander l’enregistrement RRSIG, pour debian.org, puis pour dnssec-failed.org, d’abord avec la connexion 3G Bouygues, ensuite avec une connexion propre, dans les 2 cas en interrogeant le serveur DNS de LDN (parce que je sais qu’il supporte DNSSEC). Le résultat est intéressant…

– Connexion Bouygues 3G

Pour debian.org :

me@laptop:~$ dig @80.67.188.188 +dnssec +cdflag debian.org ; <<>> DiG <VERSION> <<>> @80.67.188.188 +dnssec +cdflag debian.org ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49096 ;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;debian.org. IN A ;; ANSWER SECTION: debian.org. 26 IN A 5.153.231.4 debian.org. 26 IN A 128.31.0.62 debian.org. 26 IN A 130.89.148.14 debian.org. 26 IN A 140.211.15.34 debian.org. 26 IN A 149.20.20.22 ;; Query time: 704 msec ;; SERVER: 80.67.188.188#53(80.67.188.188) ;; WHEN: Thu Sep 22 20:14:32 CEST 2016 ;; MSG SIZE rcvd: 119

On utilise le +cdflag (Checking Disabled) pour dire au serveur DNS de donner le champs RRSIG sans vérifier la signature. Sans quoi, si la signature est erronée, on aura comme réponse status: SERVFAIL, et aucun champs DNS, même pas les IP. Or là, on pas du tout de champs RRSIG pour un nom de domaine qui a pourtant une signature valide…

Puis pour dnssec-failed.org :

me@laptop:~$ dig @80.67.188.188 +dnssec +cdflag www.dnssec-failed.org ; <<>> DiG <VERSION> <<>> @80.67.188.188 +dnssec +cdflag www.dnssec-failed.org ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6583 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;www.dnssec-failed.org. IN A ;; ANSWER SECTION: www.dnssec-failed.org. 6747 IN A 68.87.109.242 www.dnssec-failed.org. 6747 IN A 69.252.193.191 ;; Query time: 224 msec ;; SERVER: 80.67.188.188#53(80.67.188.188) ;; WHEN: Thu Sep 22 20:16:46 CEST 2016 ;; MSG SIZE rcvd: 8

Exactement le même résultat… or on sait que ce nom de domaine a une signature DNSSEC (volontairement erronée, mais existante), on devrait avoir un champs RRSIG car on a mis l’option +cdflag.

D’ailleurs, si vous avez l’habitude d’utiliser dig, vous avez remarqué que vers la fin de la réponse, il y a l’IP du serveur qui répond, et que ici, on a bien l’IP du serveur interrogé… Et pourtant j’insiste, le résolveur DNS interrogé supporte DNSSEC.

On refait les mêmes tests, sans l’option +cdflag, sur une connexion fixe, car on veut justement vérifier la validité de la signature.

– Connexion fixe

Pour debian.org :

me@laptop:~$ dig @80.67.188.188 +dnssec debian.org ; <<>> DiG <VERSION> <<>> @80.67.188.188 +dnssec debian.org ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22069 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ;; QUESTION SECTION: ;debian.org. IN A ;; ANSWER SECTION: debian.org. 109 IN A 140.211.15.34 debian.org. 109 IN A 149.20.20.22 debian.org. 109 IN A 5.153.231.4 debian.org. 109 IN A 128.31.0.62 debian.org. 109 IN A 130.89.148.14 debian.org. 109 IN RRSIG A 8 2 300 20161031065252 20160921055252 7866 debian.org. ZERtXROfGeAS+NYTa3BaDk/Q41QkuiimerRJ9+6WMSIeKNUnfPOJR01+ Y1KzxZ9bxhVJMaeLKeYs7eQmmOFiv1tIVb5fgQRjMdMn+1QyZZEz84Ru 9K5Udohml9wboEsQNEv+ejTSVjyDoZHwdBbZjZ9ToOt4v9bGLgCAXMu/ FjkFXJDyk5wJs3g9VgnrAYx3oHoIQFVALtu8u+bktVvDsHv+8rXbjkBv e6GkB1vAvh5HQ0X/cQbQ0lekFI8FtXFT ;; Query time: 51 msec ;; SERVER: 80.67.188.188#53(80.67.188.188) ;; WHEN: Thu Sep 22 19:54:48 CEST 2016 ;; MSG SIZE rcvd: 353

Et là, on a une signature DNSSEC…

Puis pour dnssec-failed.org :

me@laptop:~$ dig @80.67.188.188 +dnssec www.dnssec-failed.org ; <<>> DiG <VERSION> <<>> @80.67.188.188 +dnssec www.dnssec-failed.org ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 5061 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ;; QUESTION SECTION: ;www.dnssec-failed.org. IN A ;; Query time: 147 msec ;; SERVER: 80.67.188.188#53(80.67.188.188) ;; WHEN: Thu Sep 22 19:56:34 CEST 2016 ;; MSG SIZE rcvd: 50

On a exactement le comportement attendu, à savoir le refus de résolution d’adresse avec le message d’erreur status: SERVFAIL. En refaisant ce dernier test avec l’option +cdflag, on aura les IP et le champs RRSIG (certes signature invalide mais visible quand même).

A ce stade, ça pue déjà pas mal le Man In The Middle, je soupçonne très fortement Bouygues d’utiliser des proxies, qui en plus de faire du MITM, modifient les adresses sources pour mentir, en mettant l’IP du serveur interrogé pour chaque requête (règles iptables DNAT), voire champs SERVER: 80.67.188.188#53 (80.67.188.188).

Mais non, tu vois la mal partout, il y a une autre explication !

J’en doute très fort, mais supposons qu’il y a une autre explication, et que je soit parano… Alors on refait des tests suivants sur la connexion Bouygues 3G, avec des IP prises au hasard.

Le test est simple, prendre une IP au hasard, supposer que c’est un résolveur DNS, et l’utiliser dans la commande dig, pour interroger le serveur correspondant… et ensuite faire un nmap sur cette IP pour voir ce que c’est comme serveur, et on peut même faire un whois, pour bien voir que ça n’appartient pas aux ranges Bouygues Telecom.

Tomber du premier coup sur un vrai résolveur DNS public, j’y crois pas trop mais j’ai quand même fait le test avec 5 ou 6 différentes en tout (les 3 tests, dig, nmap et whois pour chaque IP), avec toujours le même résultat que l’exemple suivant, Je met qu’un seul pour ne pas écrire un pavé. L’exemple en question concerne l’IP 138.2.4.6, prise vraiment au hasard, qui appartient au range d’Oracle. Les autres IP que j’ai testé appartiennent entre autre à Cogent, IANA et j’en passe… avec d’interroger le serveur avec dig sur la connexion Bouygues 3G, commençons par dissiper le doute, on le fait d’abord sur une connexion fixe, certes pas la plus neutre du monde, mais un peu plus propre que la 3G chez Bouygues.

dig @138.2.4.6 +dnssec debian.org ; <<>> DiG <VERSION> <<>> @138.2.4.6 +dnssec debian.org ; (1 server found) ;; global options: +cmd ;; connection timed out; no servers could be reached

Voilà, ça répond pas, car ce n’est pas un résolveur DNS public, voir pas un résolveur DNS du tout. Pourtant, le même test chez Bouygues donne… une réponse, très similaire au test réalisée plus haut, avec le résolveur de LDN.

me@linuxbox:~$ dig @138.2.4.6 +dnssec debian.org ; <<>> DiG <VERSION> <<>> @138.2.4.6 +dnssec debian.org ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14422 ;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;debian.org. IN A ;; ANSWER SECTION: debian.org. 300 IN A 140.211.15.34 debian.org. 300 IN A 149.20.20.22 debian.org. 300 IN A 5.153.231.4 debian.org. 300 IN A 128.31.0.62 debian.org. 300 IN A 130.89.148.14 ;; Query time: 229 msec ;; SERVER: 138.2.4.6#53(138.2.4.6) ;; WHEN: <DATE> ;; MSG SIZE rcvd: 119

Une réponse à une requête DNS en interrogeant un serveur qui ne fait pas de DNS, voir pas un serveur du tout (IP prise au hasard pour rappel), il y a qu’une explication, un proxy qui fait du Man-In-The-Middle, intercepte et traite tous les requêtes DNS, en mentant sur l’origine des paquets réponses (voire le champs ;; SERVER:)

J’y crois pas, pourquoi ils se seraient donner tout ce mal ?

Je vous épargne la sortie du whois, pour vérifier que ce range d’IP appartient bien à Oracle et non pas à Bouygues Telecom… c’est vérifiable depuis n’importe quelle connexion Internet. Par contre, la sortie de nmap, effectué sur le réseau 3G de Bouygues, est beaucoup plus intéressante… Avant d’aller plus loin, une précision, si vous essayer nmap -Pn 138.2.4.6 sur une connexion à peu près propre, sans proxy qui fait du MITM, vous aurez comme réponse All 1000 scanned ports on 138.2.4.6 are filtered, un serveur DNS (port 53) qui répond sur Internet, mais dont tous les 1000 1ers ports (1-1000) sont filtrés, c’est quand même curieux…

Sur une connexion 3G Bouygues, ça donne ça…

me@linuxbox:~$ sudo nmap -A 138.2.4.6 Starting Nmap <VERSION> ( http://nmap.org ) at <DATE> Nmap scan report for 138.2.4.6 Host is up (0.13s latency). Not shown: 993 filtered ports PORT STATE SERVICE VERSION 21/tcp open ftp? |_ftp-bounce: no banner 25/tcp open smtp Postfix smtpd |_smtp-commands: Couldn't establish connection on port 25 53/tcp open domain ISC BIND hostmaster 80/tcp open http? 554/tcp open rtsp? 1723/tcp open pptp? |_pptp-version: ERROR: Script execution failed (use -d to debug) 8080/tcp open http-proxy? Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port OS fingerprint not ideal because: Missing a closed TCP port so results incomplete No OS matches for host Network Distance: 4 hops Service Info: Host: smtp-proxy-1b.bouyguesbox.fr TRACEROUTE (using port 80/tcp) HOP RTT ADDRESS 1 2.36 ms 10.42.0.1 2 75.44 ms 10.125.12.239 3 81.89 ms 10.125.14.234 4 94.37 ms 138.2.4.6 OS and Service detection performed. Please report any incorrect results at http://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 358.62 seconds

Tout d’un coup, il y a plein de services qui tournent… Mais surtout, il y a un bon gros champs Service Info qui ne laisse aucun pas de doute sur le fait qu’on a bien à faire à proxy (pas si) transparent (que ça), appartenant à Bouygues Telecom

Service Info: Host: smtp-proxy-1b.bouyguesbox.fr

Et sur lequel il y a bien un serveur DNS prêt à intercepter vos requêtes, et à les rediriger vers le résolveur DNS de Bouygues, qui répond à la place du serveur qu’on croit avoir interrogé, en cassant DNSSEC au passage…

53/tcp open domain ISC BIND hostmaster

Mais encore ?

On sait qu’il y a un DNS menteur, qui ne semble pas supporter DNSSEC (Le champs RRSIG dans les requêtes dig qui finit toujours chez Dave Null), mais on sait toujours pas pourquoi on reçoit des signatures erronés d’après DNSSEC/TLSA Validator… là pour le coup, j’ai pas une explication aussi complète, mais peut-être un début d’explication (conf foireuse pour la partie DNSSEC?)

Lors des requêtes DNS, soit avec dig +dnssec soit DNSSEC/TLSA Validator (j’ai pas determiné le moment exact), je reçois des paquets DNSKEY, contenant une clé publique, et issus avec comme IP source, plusieurs IP délirantes, appartenant à des ranges/entités différentes…



Je sais pas exactement ce que Bouygues Telecom fout, ni pourquoi j’ai clés DNSSEC qui sont fausses (erreurs DNSSEC visibles sur TLSA Validator pour tous les sites visités depuis la connexion Bouygues mobile concernée par le MITM, et seulement depuis ladire connexion), Mais dans tous les cas, ça pue. En tout cas si quelqu’un à plus d’infos à ce sujet, ça m’intéresse…

Conclusion

Ça pue très fort, parce qu’on peut pas utilser le DNS qu’on veut. Quelque soit celui configuré sur el système, le proxy de Bouygues intercepte les requêtes DNS, pour que le résolveur de Bougyes y réponde à la place du résolveur qu’on voulait interroger, et à l’insu de l’utilisateur.

Et je pense pas que Bouygues soit le seul à faire ce genre de magouilles. Si vous avez l’occasion de faire des tests sur des connexions agrumes télécom, SFR, ou encore Free, les retours m’intéressent. La solution la plus simple que je vois actuellement (2017), c’est de passer par un tunnel OpenVPN [1], dont le point de sortie doit se situer sur le même LAN, voire sur la même machine (de confiance) que le résolveur DNS qu’on utilise… il reste le problème de la requête première requête DNS pour établir la connexion VPN. Soit il faudra se connecter au VPN en spécifiant directement l’IP publique du serveur VPN, soit il faudra utiliser /etc/hosts (accès root évidemment nécessaire).

[1] Si c’est pas filtré, j’ai pas encore eu l’occasion de tester. Mais si jamais c’est filtré, on peut tenter de passer le flux VPN dans le port TCP 443, mais ça nécessite que le serveur utilisé soit configuré pour, et ça risque de créer de l’overhead au niveau de la bande passante/quantité de data utilisée (Il reste à vérifier si ce surplus reste dans la limite du raisonnable).