Obtenir l'adresse MAC de périphériques en utilisant Python
-
20-09-2019 - |
Question
Je suis à la recherche d'un moyen (avec python) pour obtenir l'adresse de layer II
à partir d'un périphérique sur mon réseau local. adresses Layer III
sont connues.
Le but est de construire un script qui Interroger les bases de données d'adresses IP à intervalles réguliers assurant que les adresses MAC n'ont pas changé et si elles ont, alertes e-mail à moi-même.
La solution
Pour répondre à la question avec Python dépend de votre plate-forme. Je n'ai pas de Windows à portée de main, donc la solution suivante fonctionne sur la boîte Linux je l'ai écrit sur. Un petit changement à l'expression régulière fera fonctionner sous Mac OS X.
D'abord, vous devez ping la cible. Cela placera la cible - tant qu'il est dans votre masque de réseau, qu'il sonne comme dans cette situation, il sera - dans le cache ARP de votre système. Observer:
13:40 jsmith@undertow% ping 97.107.138.15
PING 97.107.138.15 (97.107.138.15) 56(84) bytes of data.
64 bytes from 97.107.138.15: icmp_seq=1 ttl=64 time=1.25 ms
^C
13:40 jsmith@undertow% arp -n 97.107.138.15
Address HWtype HWaddress Flags Mask Iface
97.107.138.15 ether fe:fd:61:6b:8a:0f C eth0
Sachant que, vous faites un peu de magie subprocess - sinon vous écrivez du code de vérification du cache ARP vous, et vous ne voulez pas faire cela:
>>> from subprocess import Popen, PIPE
>>> import re
>>> IP = "1.2.3.4"
>>> # do_ping(IP)
>>> # The time between ping and arp check must be small, as ARP may not cache long
>>> pid = Popen(["arp", "-n", IP], stdout=PIPE)
>>> s = pid.communicate()[0]
>>> mac = re.search(r"(([a-f\d]{1,2}\:){5}[a-f\d]{1,2})", s).groups()[0]
>>> mac
"fe:fd:61:6b:8a:0f"
Autres conseils
Il y avait un question similaire répond pas trop longtemps Il y a sur ce site. Comme mentionné dans la réponse choisie par le demandeur de cette question, Python ne dispose pas d'une manière intégrée pour le faire. Vous devez soit appeler une commande de système tel que arp
pour obtenir des informations ARP, ou générer vos propres paquets en utilisant Scapy .
Modifier Un exemple en utilisant Scapy de leur site web :
Voici un autre outil qui surveiller en permanence toutes les interfaces sur un machine et imprimer toutes les demandes ARP il voit, même sur les trames 802.11 d'une Carte Wi-Fi en mode moniteur. Noter la store = 0 paramètre à reniflement () pour éviter stocker tous les paquets dans la mémoire pour rien.
#! /usr/bin/env python
from scapy import *
def arp_monitor_callback(pkt):
if ARP in pkt and pkt[ARP].op in (1,2): #who-has or is-at
return pkt.sprintf("%ARP.hwsrc% %ARP.psrc%")
sniff(prn=arp_monitor_callback, filter="arp", store=0)
Pas exactement ce que vous cherchez, mais certainement sur la bonne voie. Amusez-vous!
On dirait que vous voulez surveiller usurpateurs ARP? Dans ce cas, tout ce que vous avez besoin est arpwatch , disponible dans toutes les distributions Linux bien fourni près de chez vous . Télécharger les sources ici: http://ee.lbl.gov/
pour les systèmes Unix:
#!/usr/bin/env python2.7
import re
import subprocess
arp_out =subprocess.check_output(['arp','-lan'])
re.findall(r"((\w{2,2}\:{0,1}){6})",arp_out)
renvoie la liste des tuples avec macs. scapy est un outil extraordinaire, mais semble être surpuissant pour ce cas
Linux vous sometimems manquez la ligne de commande util "arp". L'image de l'environnement embarqué linux par exemple d'un base.
Une autre façon sans l'outil "arp" serait de lire et d'analyser le fichier / proc / net / arp:
root@raspberrypi:~# cat /proc/net/arp
IP address HW type Flags HW address Mask Device
192.168.1.1 0x1 0x2 xx:xx:xx:xx:xx:xx * wlan0
192.168.1.33 0x1 0x2 yy:yy:yy:yy:yy:yy * wlan0
d'une manière plus facile, si sur linux:
print os.system('arp -n ' + str(remoteIP))
vous obtiendrez:
Address HWtype HWaddress Flags Mask Iface
192.168..... ether 9B:39:15:f2:45:51 C wlan0
Une solution simple à l'aide scapy, pour analyser le sous-réseau 192.168.0.0/24 est la suivante:
from scapy.all import *
ans,unans = arping("192.168.0.0/24", verbose=0)
for s,r in ans:
print("{} {}".format(r[Ether].src,s[ARP].pdst))
Essayez d'utiliser les netifaces trouvés ici. netifaces
Mise à jour générale pour Python 3.7. Remarque: l'option -n
pour arp
ne fournit pas la liste des arp sur les systèmes Windows comme prévu certaines réponses pour les systèmes à base de Linux. Utilisez l'option -a
comme indiqué dans la réponse ici.
from subprocess import Popen, PIPE
pid = Popen(['arp', '-a', ip], stdout=PIPE, stderr=PIPE)
IP, MAC, var = ((pid.communicate()[0].decode('utf-8').split('Type\r\n'))[1]).split(' ')
IP = IP.strip(' ')
MAC = MAC.strip(' ')
if ip == IP:
print ('Remote Host : %s\n MAC : %s' % (IP, MAC))