Fiabilisation du détournement d'un Dash Button pour l'utiliser comme bouton wifi.

Contexte 


Dans l'article précédent ( ici ) que j'avais rédigé concernant le détournement des dash button, je m'étais appuyé sur du code python utilisant la librairie scapy.
Le principe était simple : je lançais une fonction qui "sniffait" les trames ethernet et dès qu'elle détectait une trame ARP associée à l'adresse MAC d'un dash button, je faisais exécuter une fonction.

Le problème est que cela ne fonctionnait pas toujours parfaitement. Par exemple, après 24h sans avoir appuyé sur le bouton, il fallait que j’appuie deux fois pour que la fonction se déclenche.
Pas très pratique et pas très fiable !

J'ai donc décidé de creuser le sujet pour aboutir à une solution présentant un taux de fiabilité compatible avec mes objectifs que je décris .

PS: En cliquant sur ce lien vous pourrez acheter des Dash Button sur Amazon et m'encourager en me faisant gagner 1 centime ! La fortune ! 



La librairie socket


La clé de voûte de ce projet est de réussir à trouver du code python fiable et robuste. Comme bien souvent ce sont les choses les plus simples qui le sont, j'ai fait quelques recherches à partir de programmes utilisant la librairie socket.

Le résultat de mes recherche est le code ci-dessous :



try:
     rawSocket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003))
     while True: 
          packet = rawSocket.recvfrom( 2048 )
          ethernet_header = packet[0][0:14]
          ethernet_detailed = struct.unpack( "!6s6s2s" , ethernet_header)

         # On va regarder le type de trame Ethernet
         ethertype = ethernet_detailed[2]
         arp_header = packet[0][14:42]
         arp_detailed = struct.unpack("2s2s1s1s2s6s4s6s4s" , arp_header)
         macSource = binascii.hexlify(ethernet_detailed[1] )
         if ( ethertype == '\x00\x06' ):




Je ne suis pas un expert en programmation réseau de bas niveau et je ne comprends pas grand chose à comment fonctionnent les différents protocoles Ethernet.Mais avec ce petit morceau de code j'ai réussi à écrire un programme complet qui me permet de :
- detecter l'adresse MAC d'un nouveau bouton qui ne serait pas connu.
- sniffer toutes les trames ethernet qui passent.

Pour commencer j'ai étudié toutes les trames avec notamment les types de trame en faisant afficher les champs ci dessous :

log.info( "****************_ETHERNET_FRAME_****************" )
log.info( "Dest MAC:       " + binascii.hexlify( ethernet_detailed[0] ) )
log.info( "Source MAC:      " + binascii.hexlify(ethernet_detailed[1]))
log.info( "Type:            " + binascii.hexlify(ethertype) )

Ensuite, j'ai identifié les adresse MAC connues. J'ai donc pu repérer les adresses MAC de mes Dash Button.

Ethernet 



Pour chaque pression sur un dash button j’obtenais 3 types de trames :
  1. ethertype == '\x00\x06'
  2. ethertype == '\x08\x06'
  3. ethertype == '\x08\x00' (deux fois).
0806 Correspond à la trame ARP. Elle n'est pas totalement fiable car ne se répand sur tous le LAN que si les tables ARP nécessitent une mise à jour. 
0800 correspond à une trame contenant un protocole IP. Comme ces deux trames apparaissent à chaque connexion du bouton, je suppose qu'il s'agit des requêtes DHCP. Mais comme ces trames sont toujours doubles je ne les ais pas exploitées (mais c'est faisable si on regarde laquelle contient une adresse IP source). 
0006 est plus complexe à comprendre. Il ne s'agit pas d'une trame de type Ethernet v2 mais de type 802.3. Pour comprendre cela il faut se plonger dans l'étude d'Ethernet. Ce qu'il faut savoir c'est qu'historiquement il y a plusieurs normes et plusieurs versions qui régissent les trames Ethernet sur un LAN. Quand l'Ethertype a une valeur inférieur à 1500 il s'agit de trame suivant la norme 802.3. Sinon on est en Ethernet. 
J'ai un peu cherché et il semble que la valeur 0006 de cette trame indique qu'elle contient un protocole LLC. Apparemment cette trame est utilisée pour faire le lien avec l'équipement en wifi. 
(ça je n'ai pas réussi à vraiment comprendre).

Mais j'avais atteint mon objectif : réussir à trouver un code qui arrive à détecter la présence d'une trame unique qui apparaît dès qu'un dash button se connecte. 

Pour compléter mon inspection du réseau, j'ai ajouté ce morceau de code pour afficher les information contenues dans les trames ARP ( ethertype == '\x08\x06' )


log.info( "******************_ARP_HEADER_******************" )
log.info( "Hardware type:   " + binascii.hexlify(arp_detailed[0]) )
log.info( "Protocol type:   " + binascii.hexlify(arp_detailed[1]))
log.info( "Hardware size:   " + binascii.hexlify(arp_detailed[2]))
log.info( "Protocol size:   " + binascii.hexlify(arp_detailed[3]))
log.info( "Opcode:          " + binascii.hexlify(arp_detailed[4]))
log.info( "Source MAC:      " + binascii.hexlify(arp_detailed[5]))
log.info( "Source IP:       " + socket.inet_ntoa(arp_detailed[6]))
log.info( "Dest MAC:        " + binascii.hexlify(arp_detailed[7]))
log.info( "Dest IP:         " + socket.inet_ntoa(arp_detailed[8]))
log.info( "*************************************************\n")

Au final j'ai écrit un programme qui se lance avec la crontable au boot du Raspi et qui pour chaque adresse MAC d'un dash button survenant dans une trame de type 0006, lance la fonction associée.

Pour le moment j'ai écris deux fonctions : 
- Une fonction qui compte mes sacs de pellets. Dès que j'alimente mon poil à pellets, j'appuie sur le bouton. Cela me permettra de suivre la consommation.
- Une fonction qui m'indique la dernière date d'arrosage des plantes.



Soutenez la blogoculture ...


Le plus simplement du monde, si vous avez un achat à faire sur Amazon, accédez au site à partir de ce lien (que vous pouvez ajouter dans vos favoris)https://amzn.to/2nbe4sm




Soutenez la blogoculture ...


Le plus simplement du monde, si vous avez un achat à faire sur Amazon, accédez au site à partir de ce lien (que vous pouvez ajouter dans vos favoris)https://amzn.to/2nbe4sm


... mais aussi ...


Vous appréciez les articles frais et vitaminés de ce blog et vous voulez faire un geste pour encourager ce partage, saluer le travail, ou parce que vous y avez trouvé des choses utiles ( et que vous êtes sympa ) ?

... c'est possible et vous avez le choix !
Si vous avez un compte Paypal et quelques euros à offrir sans vous mettre sur la paille, subventionnez la culture domotique à l'ancienne !
Vous ne dépenserez pas un radis de plus en faisant un achat sur eBay à partir de ce lien.
Economisez du blé avec Amazon Prime ! Offre d'essais 1 mois gratuit (et renouvelable).
Soyez chou et aidez les petits producteurs de blog à se faire connaitre auprès de vos amis facebook !

Merci

Commentaires