Получение MAC-адреса с устройств с помощью Python
-
20-09-2019 - |
Вопрос
Я ищу способ (с помощью python) получить layer II
адрес с устройства в моей локальной сети. Layer III
адреса известны.
Цель состоит в том, чтобы создать скрипт, который будет регулярно опрашивать базы данных IP-адресов, гарантируя, что mac-адреса не изменились, и, если они изменились, отправлять мне оповещения по электронной почте.
Решение
Ответ на вопрос с помощью Python зависит от вашей платформы.У меня нет Windows под рукой, поэтому следующее решение работает в Linux-блоке, на котором я его написал.Небольшое изменение регулярного выражения заставит его работать в OS X.
Во-первых, вы должны пропинговать цель.Это поместит цель - до тех пор, пока она находится в вашей сетевой маске, что, похоже, в данной ситуации так и будет, - в ARP-кэш вашей системы.Наблюдать:
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
Зная это, вы совершаете небольшое волшебство с подпроцессором - в противном случае вы сами пишете код проверки кэша ARP, а вы не хотите этого делать:
>>> 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"
Другие советы
Там был один похожий вопрос ответил не так давно на этом сайте.Как упоминалось в ответе, выбранном задавшим этот вопрос, в Python нет встроенного способа сделать это.Вы должны либо вызвать системную команду, такую как arp
чтобы получить информацию ARP или сгенерировать свои собственные пакеты с помощью Скапи.
Редактировать: Пример использования Scapy с их веб-сайта:
Вот еще один инструмент, который будет постоянно контролировать всех интерфейсов машины и напечатать все ARP-запрос нем видит, даже на рамах 802.11 с Карта WiFi в режим монитора.Обратите внимание на параметр store=0 для sniff(), чтобы избежать сохранения всех пакетов в памяти для ничего.
#! /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)
Не совсем то, что вы ищете, но определенно на правильном пути.Наслаждайтесь!
Похоже, вы хотите отслеживать ARP-подделки?В этом случае все, что вам нужно, это часы arpwatch, доступно в каждом хорошо поставляемом дистрибутиве Linux рядом с вами.Скачать исходники можно здесь: http://ee.lbl.gov/
для систем на базе 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)
вернет список кортежей с mac-адресами.scapy - удивительный инструмент , но , похоже , для данного случая он излишен
В Linux иногда вы пропускаете утилиту командной строки "arp".Например, базовый образ встроенной среды yocto linux.
Альтернативным способом без инструмента "arp" было бы прочитать и проанализировать файл /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
более простой способ, если на linux:
print os.system('arp -n ' + str(remoteIP))
вы получите:
Address HWtype HWaddress Flags Mask Iface
192.168..... ether 9B:39:15:f2:45:51 C wlan0
Простое решение с использованием scapy для сканирования подсети 192.168.0.0 / 24 заключается в следующем:
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))
Попробуйте использовать сетевые интерфейсы, найденные здесь. netifaces
Общее обновление для Python 3.7.Замечание:возможность -n
для arp
не предоставляет список arp в системах Windows, как это предусмотрено в некоторых ответах для систем на базе Linux.Используйте эту опцию -a
как указано в ответе здесь.
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))