Appels Wi-Fi sur Android : quand les paquets DNS font fausse route
Sur mobile, il n’y a rien de plus frustrant quand il n’y a pas de réseau. Heureusement, de nos jours, les réseaux Wi-Fi sont partout, et grâce aux appels Wi-Fi, ou VoWiFi, il est désormais possible de passer des appels et échanger des SMS là où le réseau mobile n’a pas de couverture.
En ce qui me concerne, la VoWiFi n’avait l’air de marcher que sur les réseaux Wi-Fi des autres : celui de mes parents, de mes amis, parfois des réseaux publics ; même sur le Wi-Fi à bord des avions et avec le mode avion activé, l’icône de la VoWiFi s’affichait sur mon téléphone. Mais sur mon réseau Wi-Fi domestique, pour une raison que je n’avais jamais creusée jusqu’à maintenant, je n’avais pas de VoWiFi. Il ne s’agissait pas d’une simple erreur de configuration de mon pare-feu, mais d’un problème beaucoup plus subtil et beaucoup plus surprenant que ça. Dans ce billet, je vous propose de regarder ensemble ce qui m’a empêché de bénéficier de la VoWiFi chez moi.
Vue d’ensemble de la VoWiFi
Passons d’abord rapidement en revue les grands principes de la VoWiFi.
Là où la bonne vieille 2G (ou GSM) avait un fonctionnement plutôt proche du RNIS et des réseaux à commutation par circuit, les réseaux mobiles modernes (4G ou 5G) sont, dans les grandes lignes, devenus des réseaux où les appels et les SMS passent en IP. Ce qui fait que la très grande majorité des usagers d’un réseau 4G ou 5G tient dans la main un client SIP sans le savoir.
Il n’y a donc plus beaucoup de différences entre un téléphone mobile connecté à un cœur de réseau d’opérateur mobile en 4G ou 5G et le même téléphone sur lequel on aurait installé un client SIP pour accéder à un serveur Asterisk en Wi-Fi. Alors, qu’est-ce qui empêcherait ce même téléphone d’accéder au cœur de réseau de son opérateur mobile en Wi-Fi plutôt qu’en 4G ou 5G ?
Du point de vue de l’opérateur téléphonique, un réseau Wi-Fi n’est pas un réseau de confiance : l’administrateur d’un tel réseau pourrait faire ce qu’il veut, comme espionner le trafic entre les téléphones et le cœur de réseau, et peut-être récupérer des identifiants et ainsi compromettre le réseau de l’opérateur par ce biais. Pour que la VoWiFi se fasse en toute sécurité, la solution est donc de faire appel à un VPN avec une authentification forte.
Et c’est ce qui se passe dans la pratique : pour mettre en place la VoWiFi, l’équipement utilisateur (user equipment ou UE, le jargon de la 3GPP par lequel on désigne un téléphone) monte un tunnel IPSec entre lui et le cœur de réseau, au moyen d’une passerelle appelée Evolved Packet Data Gateway (ePDG) servant de point d’entrée dans le cœur de réseau de l’opérateur. Ensuite, une fois le tunnel IPSec monté, l’UE s’inscrit auprès de la fonction téléphonie du cœur de réseau utilisant le protocole SIP et sa méthode REGISTER. L’authentification SIP ne se fait non pas par un nom d’utilisateur et par un mot de passe comme on le ferait d’habitude, mais par une méthode propre qui implique des secrets stockés dans la carte SIM inséré dans l’UE.
Le nom d’hôte de l’ePDG est préalablement configuré par l’opérateur téléphonique : par exemple, chez Orange ou Sosh, l’ePDG est epdg.epc.mnc001.mcc208.pub.3gppnetwork.org
. Sitôt l’UE connecté à un réseau Wi-Fi, la première chose à faire pour mettre en place la VoWiFi est donc de résoudre ce nom de domaine par des requêtes DNS de type A ou AAAA. Dans le cas d’Orange, à date, on obtient deux adresses IPv4 et zéro adresse IPv6.
Et c’est justement la résolution DNS du nom de l’ePDG qui ne fonctionnait pas chez moi.
J’ai rapidement exclu un surblocage dû à un pare-feu, car toutes les autres résolutions DNS effectuées par le système Android fonctionnent correctement. En outre, le trafic sortant utilisant le protocole ESP et vers les ports 500 et 4500 en UDP (respectivement pour ISAKMP et l’encapsulation d’ESP dans UDP), requis pour IPSec, est autorisé sur mon réseau. La cause du non-fonctionnement des appels Wi-Fi n’était donc pas du fait du réseau…
Le problème
Il se trouve que le réseau Wi-Fi typique d’un particulier possède une passerelle qui fait tout : borne Wi-Fi, switch, routeur, serveur DHCP, mais surtout, résolveur DNS. Or cela fait plus de dix ans que le résolveur DNS est distinct du routeur sur mon réseau domestique ; j’ai même repris récemment l’architecture de ce réseau pour que le service de résolution DNS soit fourni par deux jails sur deux machines FreeBSD distinctes pour éviter les points de défaillance unique sur le DNS. Ce qui donne une architecture qui se rapproche davantage d’un réseau d’entreprise que de celui d’un particulier, comme illustré sur l’exemple de la figure ci-dessous.
Pour dépanner la VoWiFi sur mon réseau, j’avais fait un tcpdump sur la passerelle. C’est là où j’ai vu passer du trafic DNS venant du téléphone, destiné à un des deux résolveurs DNS du réseau local… mais capturé par le routeur.
Or il m’a fallu un moment pour remarquer un détail très sournois : j’avais capturé sur mon routeur des paquets DNS dont l’adresse IP destinataire était celui du résolveur DNS… mais dont l’adresse MAC destinataire était celle de la passerelle par défaut, et non pas celle du résolveur. En toute logique, ces paquets étaient rejetés par le routeur, car l’adresse IP de destination ne correspondait pas à une adresse configurée sur l’interface Ethernet.
C’est donc comme si la table ARP était fausse. Sauf que toutes les autres résolutions DNS fonctionnaient correctement sur le mobile, donc la table ARP du système n’était pas en cause. Le problème est masqué sur les réseaux où la passerelle (donc la box Internet) fait aussi office de résolveur DNS.
Le plus bizarre, c’est que ce bug n’est pas nouveau. Un commentaire sur un ticket ouvert chez Google, ouvert en avril 2021, rejette la faute sur Qualcomm et précise qu’il s’agit d’un bug connu chez eux. Qualcomm est entre autres le fabricant d’une gamme de processeurs de bande de base (ou basebands), circuits intégrés mettant en œuvre la pile de protocoles radio nécessaires aux communications mobiles.
L’affirmation que le bug soit chez Qualcomm me paraît plausible : puisque les secrets nécessaires pour l’authentification SIP se trouvent dans la carte SIM, il est tout à fait concevable que le processeur de bande de base les garde jalousement et soit le seul à y avoir accès.
Enfin, puisque mon téléphone contient un chipset Qualcomm, j’étais sans doute affecté par ce même bug.
Un contournement possible
Étant donné que je souhaitais très fortement faire que les appels Wi-Fi fonctionnent chez moi, il me fallait un moyen de contourner ce bug. Voilà comment j’ai procédé.
J’ai commencé par démarrer un serveur DNS sur le routeur, configuré pour rediriger toute requête vers l’un des deux jails faisant office de résolveurs DNS officiels de mon réseau.
Ensuite, il faudrait modifier la liste des serveurs DNS poussés par DHCP pour que le seul serveur DNS soit celui de la passerelle. Je considère cela comme un honteux bidouillage et il est souhaitable de le restreindre aux machines sous Android, de sorte à ne pas perturber les autres systèmes d’exploitation.
Heureusement, avec ISC DHCPD, on peut pousser des éléments de configuration de
manière conditionnelle. Et pour cibler Android, on vérifie si l’option
vendor-class-identifier envoyée dans le DHCPDISCOVER ou DHCPREQUEST commence
par la chaîne android-dhcp-
. Comme ceci :
subnet 192.0.2.0 netmask 255.255.255.0 {
range 192.0.2.100 192.0.2.200;
option routers 192.0.2.254;
option domain-name "home.arpa";
option domain-search "home.arpa";
if substring(option vendor-class-identifier, 0, 13) = "android-dhcp-" {
option domain-name-servers 192.0.2.254;
/* Alternative :
* option domain-name-servers 192.0.2.254, 192.0.2.10, 192.0.2.11; */
} else {
option domain-name-servers 192.0.2.10, 192.0.2.11;
}
}
Après avoir redémarré le serveur DHCP, je me suis déconnecté, puis reconnecté à mon réseau Wi-Fi sur le téléphone. Au bout de cinq à dix secondes, l’icône symbolisant la VoWiFi est apparue. Victoire ! Pendant ce temps, les autres machines continuent de recevoir par DHCP la liste inchangée des résolveurs DNS.
Une méthode alternative aurait été de désigner les téléphones sous Android par leurs adresses MAC. Mais ce n’est à mon avis pas une bonne idée : la plupart des téléphones utilisent des adresses MAC aléatoires par défaut, ce qui ne se désactive que par des manipulations directement sur le terminal. Et je ne souhaite pas non plus recenser les adresses MAC des terminaux des amis qui seraient de passage chez moi. Ce serait fastidieux à gérer. C’est pour cela que j’estime qu’il vaut mieux différencier suivant le vendor-class-identifier.
Conclusion
Vous savez maintenant pourquoi, dans certains cas, les appels Wi-Fi ne fonctionnent pas sur Android et comment contourner le bug dans une situation analogue à la mienne.
Le code erroné est déployé dans ce que je présume être des processeurs de bande de base qui ont été fabriqués dans de très grandes séries. Je serais donc curieux de savoir à quel point ce bug a été observé ailleurs. Mes recherches au moment où je cherchais à résoudre le problème ne m’ont en effet donné que très peu d’indices. Alors, puisse ce billet de blog être un indice de plus.
Commentaires
Poster un commentaire
Poster un commentaire