跨网络获取IP的MAC地址
希望大家都好。
我想请教一下你们,或者给我指个方向。我现在在做一个关于网络管理的项目。由于时间紧迫,我尽量使用开源代码来帮助我。现在遇到的问题是,我需要获取所有连接到网络的设备的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地址非常简单,所以这并不是一个可靠的方法。
总的来说,我认为你应该换个思路;比如,有很多网络资产管理系统,你可以直接使用其中一个,并与它进行对接。