我正在寻找一种方法(使用python)从本地网络上的设备获取第二层地址。第三层地址是已知的。
目标是构建一个脚本,定期轮询IP地址数据库,确保mac地址没有改变,如果有,则向我自己发送电子邮件警报。
答案 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))