使用Python从设备获取MAC地址

时间:2009-11-17 18:24:09

标签: python ip-address mac-address

我正在寻找一种方法(使用python)从本地网络上的设备获取第二层地址。第三层地址是已知的。

目标是构建一个脚本,定期轮询IP地址数据库,确保mac地址没有改变,如果有,则向我自己发送电子邮件警报。

9 个答案:

答案 0 :(得分:17)

使用Python回答问题取决于您的平台。我没有Windows方便,所以以下解决方案适用于我写的Linux盒子。对正则表达式的一个小改动将使它在OS X中起作用。

首先,您必须ping目标。这将放置目标 - 只要它在你的网络掩码中,听起来就像在这种情况下它将在你的系统的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"

答案 1 :(得分:5)

在这个网站上不久前有一个similar question回答。正如提问者在该问题所选择的答案中所提到的,Python没有内置的方法来实现它。您必须调用诸如arp之类的系统命令来获取ARP信息,或者使用Scapy生成您自己的数据包。

修改:使用Scapy from their website的示例:

  

这是另一种工具   不断监控a上的所有接口   机器并打印所有ARP请求它   即使在来自a的802.11帧上也能看到   监控模式下的Wi-Fi卡。请注意   store = 0参数to 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 :(得分:2)

听起来你想要监控ARP欺骗者?在这种情况下,您需要的只是arpwatch,可以在您附近的每个提供良好的Linux发行版中找到。在此处下载来源:http://ee.lbl.gov/

答案 3 :(得分:2)

对于基于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是一个了不起的工具,但对于这种情况似乎有些过分

答案 4 :(得分:2)

在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

答案 5 :(得分:1)

一种更简单的方法,如果在linux上:

void Main() { var strs = new List<string> { "A|B", "CCC|DD", "E|FFF"}; var Ts = strs.Select(s =>s.ToT() ); Ts.Dump(); } static class Ext { static public T ToT(this string str) { return new T(str); } } public class T { public string A { get; set; } public string B { get; set; } public T(string str) { var arr= str.Split('|'); A = arr[0]; B = arr[1]; } }

你会得到:

print os.system('arp -n ' + str(remoteIP))

答案 6 :(得分:1)

使用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))

答案 7 :(得分:0)

尝试使用此处找到的netifaces。 netifaces

答案 8 :(得分:0)

Python 3.7的常规更新。备注:-n的选项arp不提供Windows系统上的arp列表,而基于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))