22

我正在寻找一种方法(使用 python)layer II从本地网络上的设备获取地址。 Layer III地址是已知的。

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

4

8 回答 8

20

使用 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"
于 2009-11-17T18:44:39.887 回答
5

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

编辑:使用他们网站上的 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'

这是完全跨平台的。

不完全是您正在寻找的东西,但绝对是在正确的轨道上。享受!

于 2009-11-17T18:41:00.633 回答
3

使用 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))
于 2018-11-10T00:05:31.390 回答
2

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

于 2009-11-17T18:27:23.360 回答
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 是一个了不起的工具,但在这种情况下似乎有点矫枉过正

于 2015-07-22T23:47:24.403 回答
2

在 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
于 2016-05-15T12:11:03.400 回答
1

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

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

你会得到:

    Address        HWtype  HWaddress           Flags Mask            Iface
    192.168.....   ether   9B:39:15:f2:45:51   C                     wlan0
于 2017-05-24T20:11:56.033 回答
0

Python 3.7 的一般更新。备注: 的选项不提供 windows 系统上的 arp 列表,为基于 linux 的系统提供某些答案-n。使用此处答案中所述arp的选项。-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))
于 2019-07-05T09:14:37.127 回答