Obtener dirección MAC de dispositivos que utilizan Python
-
20-09-2019 - |
Pregunta
Estoy buscando una manera (con Python) de obtener el layer II
dirección desde un dispositivo en mi red local. Layer III
Se conocen las direcciones.
El objetivo es crear un script que sondee una base de datos de direcciones IP a intervalos regulares, asegurando que las direcciones Mac no hayan cambiado y, si lo han hecho, enviarme alertas por correo electrónico.
Solución
Para responder a la pregunta con Python depende de la plataforma. No tengo a mano de Windows, por lo que la siguiente solución funciona en la máquina Linux lo escribí en. Un pequeño cambio en la expresión regular hará que funcione en OS.
En primer lugar, se debe hacer ping al objetivo. Eso va a colocar el blanco - siempre y cuando sea dentro de su máscara de red, que suena como en esta situación será - en la caché ARP de su sistema. Observe:
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
Sabiendo que, haces un poco de magia subproceso - de lo contrario se está escribiendo caché ARP código de comprobación de sí mismo, y no quiero hacer eso:
>>> 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"
Otros consejos
Hubo una pregunta similar href="https://stackoverflow.com/questions/85577/search-for-host-with-mac-address-using-python"> no respondieron demasiado largo hace en este sitio. Como se mencionó en la respuesta elegida por el autor de la pregunta de que se trate, Python no tiene una forma integrada de hacerlo. Debe bien llamar a un comando del sistema, tales como arp
para obtener información ARP, o generar sus propios paquetes usando Scapy .
Editar Un ejemplo utilizando Scapy desde su página web :
Esta es otra herramienta que le vigilar constantemente todas las interfaces en una máquina e imprimir todos ARP soliciten ve, incluso en fotogramas de un 802.11 tarjeta Wi-Fi en modo monitor. Nota la store = 0 parámetro para sniff () para evitar almacenar todos los paquetes en la memoria para nada.
#! /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)
No es exactamente lo que está buscando, pero definitivamente en el camino correcto. Disfrutar!
Parece que usted quiere supervisar spoofers ARP? En este caso, todo lo que necesita es arpwatch , disponible en todas las distribuciones de Linux bien abastecido cerca de usted . fuentes de descarga aquí: http://ee.lbl.gov/
para sistemas basados en 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)
devolverá una lista de tuplas con macs.scapy es una herramienta increíble, pero parece excesiva para este caso.
En Linux sometimems se le pasa la línea de comandos util "arp". imagen entorno Linux incrustado Una base yocto por ejemplo.
Una forma alternativa y sin la función "arp" sería leer y analizar el archivo / 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
una manera más fácil, si en Linux:
print os.system('arp -n ' + str(remoteIP))
obtendrá:
Address HWtype HWaddress Flags Mask Iface
192.168..... ether 9B:39:15:f2:45:51 C wlan0
Una solución simple usando scapy, para escanear la 192.168.0.0/24 subred es como sigue:
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))
Trate de usar los netifaces que se encuentran aquí. netifaces
Actualización general para Python 3.7.Observación:la opción -n
para arp
no proporciona la lista de arp en sistemas Windows como se proporciona con ciertas respuestas para sistemas basados en Linux.Usa la opción -a
como se indica en la respuesta aquí.
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))