Note ajoutée depuis : le billet où j'expliquais tout le mal que je pensais de ce portier n'a pas encore refait surface dans mes backups. J'ai remplacé mon adresse IP publique de l'époque par XX.XX.XX.XX dans les traces ; les adresses distantes, elles, sont d'origine — elles font partie de la démonstration. Le texte d'origine était rédigé à la troisième personne, je l'ai remis au « je ».
Je vous ai expliqué dans un autre article que je ne recommandais absolument pas l'utilisation de ce portier vidéo : le prix est vraiment intéressant, mais le rapport qualité-prix est exécrable. Pas de chance pour vous, vous l'avez quand même acheté et vous voulez en faire quelque chose ?
Vous souhaitez récupérer l'appui sur le bouton de la sonnette du portier IP Doorbell de Neo Coolcam et déclencher une action chez vous ?
Vous l'aurez compris : ce portier n'offre aucune API à laquelle on pourrait dire « quand on appuie sur le bouton, appelle cette URL ». C'est bien dommage. Les product owners de ces boîtes électroniques devraient se renseigner un peu mieux auprès de leur clientèle !
Ce que vaut la méthode, avant de commencer
Soyons clairs tout de suite : ce qui suit est un contournement. La fonction de base n'existe pas, et il est difficile de trouver quelque chose de propre et de réalisable facilement. Cette méthode génère parfois quelques fausses alertes — vous ne pouvez donc pas l'utiliser pour, par exemple, réveiller quelqu'un ou déclencher une alarme.
Dans mon cas, elle sert à afficher l'image de la caméra de surveillance de la porte d'entrée sur la télévision, via Kodi, quand quelqu'un appuie sur le bouton. S'il y a une fausse alerte, ce n'est pas bien grave : l'image apparaît et disparaît quelques secondes plus tard.
En revanche, dans l'autre sens, c'est du 100 % : quand quelqu'un sonne, c'est détecté à chaque fois, sans exception. Zéro raté. C'est le compromis, et pour cet usage-là il me va très bien.
Le principe : écouter ce que le portier raconte à son cloud
Un objet connecté de ce genre ne sait pas travailler tout seul. À chaque événement, il va bavarder avec ses serveurs. Si on ne peut pas lui demander de nous prévenir, on peut au moins écouter ce qu'il dit aux autres.
J'utilise pour ça une analyse avec tcpdump, et je vous invite à faire la même chose sur votre propre installation : vous allez probablement arriver à isoler une adresse IP ou une trame qui part vers le cloud au moment précis où quelqu'un sonne.
Lors de mes analyses, j'ai remarqué deux choses :
- la même adresse IP distante était contactée à chaque appui sur le bouton, et toujours sur le même port ;
- un chiffre identique (277) revenait dans la ligne à chaque fois, et ne changeait jamais.
Avec ces deux constatations, vous pouvez vous baser soit sur la combinaison IP + port, soit sur IP + 277. Pour mener ce genre de test, il faut quelques notions de réseau et surtout une bonne connaissance de votre réseau local : sans savoir ce qui est normal chez vous, vous ne verrez pas ce qui est anormal.
Qu'est-ce que tcpdump ?
tcpdump est un analyseur de paquets en ligne de commande. Il permet de voir le trafic qui passe par une interface réseau — dans mon exemple, l'interface br-lan, le pont qui relie tous les équipements du réseau local.
Dans cet article, l'analyse est réalisée directement sur le routeur, un Linksys sur lequel tourne OpenWrt. C'est le bon endroit : c'est le seul point par lequel tout le trafic de la maison passe obligatoirement. Sur un PC branché sur un switch, vous ne verriez que ce qui vous est destiné.
tcpdump -i br-lan -l -vvv dst host 192.168.0.206
-i br-lan— l'interface à écouter ;-l— sortie ligne par ligne, indispensable si on veut enchaîner derrière unwhile read;-vvv— bien bavard ;dst host 192.168.0.206— on ne garde que ce qui part vers le portier. Enlevez ce filtre pour voir les deux sens.
Test 1 — ce que le cloud envoie au portier
11:51:13.024892 IP 47.88.6.65.10006 > XX.XX.XX.XX.20922: UDP, length 60
11:51:13.189065 IP 47.90.49.123.10006 > XX.XX.XX.XX.20922: UDP, length 60
11:51:13.205056 IP 139.196.111.149.10006 > XX.XX.XX.XX.20922: UDP, length 60
11:51:13.244063 IP 115.28.10.13.10006 > XX.XX.XX.XX.20922: UDP, length 60
11:51:13.675231 IP 202.181.238.11.10006 > XX.XX.XX.XX.20922: UDP, length 60
Test 2 — ce que le portier envoie au cloud
11:52:32.303700 IP XX.XX.XX.XX.20922 > 202.181.238.11.10006 : UDP, length 60
11:52:32.305070 IP XX.XX.XX.XX.20922 > 82.165.134.205.10006 : UDP, length 60
11:52:32.305088 IP XX.XX.XX.XX.20922 > 115.28.10.13.10006 : UDP, length 60
11:52:32.306242 IP XX.XX.XX.XX.20922 > 139.196.111.149.10006: UDP, length 60
11:52:32.306265 IP XX.XX.XX.XX.20922 > 47.88.6.65.10006 : UDP, length 60
11:52:32.306327 IP XX.XX.XX.XX.20922 > 47.90.49.123.10006 : UDP, length 60
11:52:32.336955 IP 82.165.134.205.10006 > XX.XX.XX.XX.20922 : UDP, length 60
11:52:32.474109 IP 47.88.6.65.10006 > XX.XX.XX.XX.20922 : UDP, length 60
Une rafale d'UDP de 60 octets vers une demi-douzaine de serveurs différents, en moins d'une seconde, et tous sur le port 10006 : c'est la signature. Le portier arrose plusieurs serveurs à la fois pour que l'application mobile puisse le joindre où qu'elle soit. Peu élégant, mais parfaitement régulier — et c'est cette régularité qui nous intéresse.
Le script qui détecte l'appui et envoie une requête
Une fois la signature identifiée, le reste tient en quelques lignes de shell. Ce script est installé directement sur le routeur OpenWrt et tourne en permanence :
#!/bin/sh
tcpdump -q -i br-lan -tttt | while read ligne
do
if echo "$ligne" | grep "sonnette" | grep "277" ; then
if echo "$ligne" | grep "almeda" ; then
echo 'non-action'
else
curl -silent 'http://requete'
fi
fi
done
Explication ligne par ligne :
tcpdump -q -ttttsort une version courte de chaque trame, horodatée avec la date complète. La sortie part directement dans la bouclewhile read, qui traite les lignes au fil de l'eau.- On filtre sur
sonnette: c'est le nom d'hôte que j'ai attribué au portier dans la configuration réseau du routeur. tcpdump affiche les noms plutôt que les adresses, ce qui rend le filtre bien plus lisible qu'une IP en dur — et surtout, ça continue de fonctionner si l'adresse change. - On filtre ensuite sur
277, le nombre qui apparaît à chaque appui sur le bouton. - Afin d'éviter une boucle sans fin, j'exclus le client
almeda— c'est le serveur domotique qui gère l'ensemble de la maison et qui, justement, va chercher l'image de la caméra pour l'afficher sur la télé. Sans cette exclusion, le trafic déclenché par l'action se remet à matcher le filtre et on repart pour un tour. - Ce qui reste déclenche le
curlvers l'URL de mon choix — chez moi, un scénario côté domotique.
Deux mots au passage : donnez un nom d'hôte à chacun de vos équipements dans le routeur. Ça ne coûte rien, et le jour où vous lisez une capture, vous relisez des noms au lieu de déchiffrer des adresses.
La trace complète, un soir de sonnerie
Voici ce que donne la même écoute, filtrée sur le nom du portier, au moment où quelqu'un appuie sur le bouton :
root@OpenWrt:~# tcpdump -q -i br-lan -tttt | grep "sonnette"
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br-lan, link-type EN10MB (Ethernet), capture size 65535 bytes
2017-08-26 22:23:13.828178 IP huaweip9.lan.17873 > sonnette.lan.20932: UDP, length 16
2017-08-26 22:23:14.910148 IP sonnette.lan.20932 > huaweip9.lan.17873: UDP, length 16
2017-08-26 22:23:15.837131 IP huaweip9.lan.17873 > sonnette.lan.20932: UDP, length 16
2017-08-26 22:23:16.361555 IP sonnette.lan.20932 > 47.88.6.65.10006: UDP, length 60
2017-08-26 22:23:16.362371 IP sonnette.lan.20932 > s17745602.onlinehome-server.info.10001: UDP, length 60
2017-08-26 22:23:16.362389 IP sonnette.lan.20932 > 202.181.238.11.10006: UDP, length 60
2017-08-26 22:23:16.363024 IP sonnette.lan.20932 > 139.196.111.149.10006: UDP, length 60
2017-08-26 22:23:16.363024 IP sonnette.lan.20932 > 115.28.10.13.10006: UDP, length 60
2017-08-26 22:23:16.391814 IP s17745602.onlinehome-server.info.10001 > sonnette.lan.20932: UDP, length 60
2017-08-26 22:23:16.523478 IP 47.88.6.65.10006 > sonnette.lan.20932: UDP, length 60
2017-08-26 22:23:16.691365 IP 202.181.238.11.10006 > sonnette.lan.20932: UDP, length 60
2017-08-26 22:23:16.717209 IP 139.196.111.149.10006 > sonnette.lan.20932: UDP, length 60
2017-08-26 22:23:16.735700 IP 115.28.10.13.10006 > sonnette.lan.20932: UDP, length 60
Les trois premières lignes sont l'application mobile qui discute avec le portier en local. Puis, à 22:23:16.36, la rafale part : cinq destinations en trois millièmes de seconde, et les réponses qui reviennent dans la foulée. C'est net, c'est franc, ça ne ressemble à rien d'autre dans la journée.
Ce qu'on voit aussi au passage
Ce n'était pas le but de la manœuvre, mais l'exercice est instructif : ce portier envoie du trafic en permanence, vers une poignée de serveurs répartis un peu partout dans le monde, sans qu'on sache trop ce qu'il raconte ni à qui. C'est le lot commun de ce type de matériel bon marché.
Si ça vous chagrine — et ça devrait un peu —, l'endroit pour agir est le même que celui où l'on a écouté : le routeur. On peut parfaitement isoler ce genre d'objet dans son coin du réseau et lui interdire de sortir. Mais alors l'application mobile ne fonctionnera plus, puisque tout passe par le cloud du fabricant. À vous de choisir votre camp ; le mien est fait.
Améliorations et méthode alternative
Il reste à peaufiner le principe pour éviter les fausses alertes. Quelques pistes si vous voulez creuser :
- ajouter un anti-rebond : ignorer toute détection survenant moins de dix secondes après la précédente. C'est la modification qui rapporte le plus pour le moins d'effort ;
- compter les paquets de la rafale sur une fenêtre d'une seconde et n'agir qu'à partir de quatre ou cinq, plutôt que de réagir au premier venu ;
- relever le contenu des trames plutôt que leur seule enveloppe, avec
-X, et chercher si l'événement « bouton » se distingue du trafic de maintien de connexion.
Je vous laisse réfléchir et investiguer. À mes heures perdues, j'améliorerai le mien, mais pour mon usage personnel, c'est totalement suffisant.
Et si cette façon de faire ne vous plaît pas à cause des faux positifs, il y a une autre approche que je n'ai pas encore testée avec ce portier : installer un module qui relève la consommation électrique en direct, et considérer qu'une augmentation soudaine signifie que quelqu'un vient de sonner. Cette méthode aurait un gros avantage — elle fonctionnerait avec n'importe quel portier, y compris non connecté, puisque la consommation grimpe dès que la vidéo se met en route.