跨网络获取IP的MAC地址

1 投票
3 回答
6360 浏览
提问于 2025-04-16 12:49

希望大家都好。

我想请教一下你们,或者给我指个方向。我现在在做一个关于网络管理的项目。由于时间紧迫,我尽量使用开源代码来帮助我。现在遇到的问题是,我需要获取所有连接到网络的设备的MAC地址。

我对网络编程的了解有限,因为过去四年我一直在软件工程的其他领域工作。我现在的做法是使用nmap来获取我需要的IP地址和其他信息。但是,nmap的输出中没有MAC地址,而且我看到的资料显示它在这方面可能不太可靠。(我可能理解错了)

所以我尝试了一个两步走的方法,首先通过nmap获取包括IP地址在内的数据,这一步是没问题的。接下来,我在我的Python程序中对这些IP地址进行ping操作,这也能正常工作。但是,如何从IP地址获取MAC地址呢?我最开始想的是ping这个IP,然后从ARP表中抓取MAC地址,但我觉得这只在IP地址在同一子网时有效。更麻烦的是,部署时网络上可能会有多达5000台电脑需要记录。为了让你们了解我的Python ping方法,这里是我的代码:

import pdb, os
import subprocess
import re
from subprocess import Popen, PIPE

# This will only work within the netmask of the machine the program is running on cross router MACs will be lost
ip ="192.168.0.4"

#PING to place target into system's ARP cache 
process = subprocess.Popen(["ping", "-c","4", ip], stdout=subprocess.PIPE)
process.wait()

result = process.stdout.read()
print(result)

#MAC address from IP
pid = Popen(["arp", "-n", ip], stdout=PIPE)
s = pid.communicate()[0]

# [a-fA-F0-9] = find any character A-F, upper and lower case, as well as any number
# [a-fA-F0-9]{2} = find that twice in a row
# [a-fA-F0-9]{2}[:|\-] = followed by either a ?:? or a ?-? character (the backslash escapes the hyphen, since the  # hyphen itself is a valid metacharacter for that type of expression; this tells the regex to look for the hyphen character, and ignore its role as an operator in this piece of the expression)
# [a-fA-F0-9]{2}[:|\-]? = make that final ?:? or ?-? character optional; since the last pair of characters won't be followed by anything, and we want them to be included, too; that's a chunk of 2 or 3 characters, so far
# ([a-fA-F0-9]{2}[:|\-]?){6} = find this type of chunk 6 times in a row

mac = re.search(r"([a-fA-F0-9]{2}[:|\-]?){6}", s).groups()[0] #LINUX VERSION ARP
mac = re.search(r"(([a-f\d]{1,2}\:){5}[a-f\d]{1,2})", s).groups()[0] #MAC VERSION ARP
print(mac)

我查找了一些信息,但发现的资料似乎有点模糊。如果你们知道有什么想法或者研究方向可以帮助我,我会非常感激。

谢谢!

克里斯

3 个回答

0

你可以使用Python的scapy模块来获取MAC地址。

from scapy.all import *
def get_mac(ip_address):
    responses,unanswered = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=ip_address),timeout=2,retry=10)
# return the MAC address from a response
    for s,r in responses:
        return r[Ether].src
    return None

get_mac("192.168.31.14")
2

如果你没有连接到同一个子网,就无法获取主机的原始MAC地址,你得到的只会是最后一个路由器的MAC地址。

要想获取所有的MAC地址,唯一的方法就是在每个子网里设置一个服务器来捕捉这些地址,但我觉得这个主意有点疯狂。另外,现在伪造MAC地址非常简单,所以这并不是一个可靠的方法。
总的来说,我认为你应该换个思路;比如,有很多网络资产管理系统,你可以直接使用其中一个,并与它进行对接。

3

你不能直接获取在你网络之外的机器的MAC地址。

一个常见的网络管理方法是查询那些确实有这些信息的机器,比如连接这些机器的路由器和交换机,通常使用一种叫做SNMP的协议。路由器会保存它们直接连接的子网的ARP表(因为它们需要这些信息来完成工作),所以你可以从路由器那里获取这些信息。

关于这个问题的回答可能会帮助你找到一些Python库的代码,以便实现这个目标。

撰写回答