使用Python获取设备的MAC地址

25 投票
8 回答
80203 浏览
提问于 2025-04-15 16:07

我想用Python找出我本地网络上一个设备的第二层地址。现在我已经知道了第三层地址。

我的目标是写一个脚本,定期检查一份IP地址的数据库,确保这些设备的MAC地址没有变化。如果有变化,就给我发邮件提醒。

8 个回答

3

在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
7

不久前,这个网站上有一个类似的问题得到了回答。正如提问者选择的答案中提到的,Python本身并没有直接的方法来实现这个功能。你需要调用系统命令,比如arp,来获取ARP信息,或者使用Scapy自己生成数据包。

编辑:这是一个使用Scapy的例子,来自他们的官网

这里有一个工具,可以持续监控机器上的所有接口,并打印出它看到的所有ARP请求,甚至包括来自Wi-Fi卡在监控模式下的802.11帧。注意在sniff()中使用store=0参数,以避免将所有数据包存储在内存中。

#! /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)

你也可以做一些类似于经过验证的答案的事情。请查看https://scapy.readthedocs.io/en/latest/routing.html

>>> mac = getmacbyip("10.0.0.1")
>>> mac
'f3:ae:5e:76:31:9b'

这个方法在所有平台上都可以使用。

虽然这不是你想要的确切内容,但绝对是朝着正确的方向前进。祝你好运!

23

用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"

撰写回答