Получить MAC-адрес от устройств, использующих Python - PullRequest
17 голосов
/ 17 ноября 2009

Я ищу способ (с python) получить адрес уровня II от устройства в моей локальной сети. Адреса третьего уровня известны.

Цель состоит в том, чтобы создать сценарий, который будет опрашивать базы данных IP-адресов через регулярные промежутки времени, гарантируя, что mac-адреса не изменились, и, если они будут, отправлять оповещения по электронной почте.

Ответы [ 8 ]

17 голосов
/ 17 ноября 2009

Ответ на вопрос с 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"
5 голосов
/ 17 ноября 2009

Был похожий вопрос , на который недавно был дан ответ. Как упомянуто в ответе, выбранном тем, кто задает этот вопрос, у Python нет встроенного способа сделать это. Вы должны либо вызвать системную команду, такую ​​как arp, чтобы получить информацию ARP, либо сгенерировать свои собственные пакеты, используя Scapy .

Редактировать: Пример использования Scapy с их сайта :

Вот еще один инструмент, который будет постоянно контролировать все интерфейсы на машина и распечатать все ARP запросить его видит, даже на 802.11 кадры с Карта Wi-Fi в режиме монитора. Обратите внимание Параметр 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)

Не совсем то, что вы ищете, но определенно на правильном пути. Наслаждайтесь!

2 голосов
/ 15 мая 2016

В Linux иногда вы пропускаете командную строку util "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
2 голосов
/ 23 июля 2015

для систем на базе 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)

вернет список кортежей с macs. Scapy - удивительный инструмент, но в данном случае он кажется излишним

2 голосов
/ 17 ноября 2009

Похоже, вы хотите отслеживать ARP-спуферы? В этом случае все, что вам нужно, это arpwatch , доступный в любом хорошо поставляемом дистрибутиве Linux рядом с вами. Скачать источники здесь: http://ee.lbl.gov/

1 голос
/ 10 ноября 2018

Простое решение для сканирования подсети 192.168.0.0/24 с использованием scapy выглядит следующим образом:

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))
1 голос
/ 24 мая 2017

более простой способ, если на 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
0 голосов
/ 21 января 2014

Попробуйте использовать найденные здесь netifaces. netifaces

...