3

我有一些通过 UDP 多播侦听“公告”的代码。我可以得到发件人的 IP 地址,但我真正需要的是发件人的 MAC 地址(因为 IP 地址可以并且将会改变)。

有没有一种简单的方法可以在 Python 中做到这一点?

包含一个代码片段以供参考,但可能没有必要。

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)

# Allow multiple sockets to use the same PORT number
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

# Bind to the port that we know will receive multicast data
sock.bind((self.interface, MCAST_PORT))

# Tell API we are a multicast socket
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)

# Tell API we want to add ourselves to a multicast group
# The address for the multicast group is the third param

status = sock.setsockopt(socket.IPPROTO_IP, 
          socket.IP_ADD_MEMBERSHIP, 
          socket.inet_aton(MCAST_ADDR) + socket.inet_aton(self.interface));

data, addr = sock.recvfrom(1024)

...

4

5 回答 5

7

通常,您无法获取 mac 地址。在 LAN 上使用 ARP 可能会成功,但在 Internet 上是不可能的。

考虑您收到的数据包具有发送者的NATting路由器的 IP 地址的情况。数据包可能在途中经过了任意数量的中间机器,每台中间机器也都有 MAC 地址。支持您所追求的查找应该由谁负责?对于一路上的所有机器,发件人的mac地址完全没用,为什么还要支持那种查找呢?

而且,顺便说一句,在许多网卡上更改 mac 地址是微不足道的,因此将其用作某种唯一 ID 并不是一个明智的主意。

于 2009-11-12T13:53:48.033 回答
1

您需要的协议是AR​​P。检查此问题/答案以获取详细信息

于 2009-11-12T13:52:14.480 回答
1

我不确定是否可以获得发件人的 MAC 地址,因为 MAC 地址是链路级地址,而不是像 IP 这样的网络级地址。当包含 UDP 消息的数据包从发送方路由到接收方时,MAC 地址将在网络中的每一跳发生变化。

于 2009-11-12T13:54:18.797 回答
1

为此,您需要捕获原始以太网帧,而不仅仅是 UDP 数据包。

import socket

ETH_P_ALL=3
sock = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(ETH_P_ALL))
sock.bind((interface_name, 0))
data = sock.recv(2000)
dmac = data[:6]
smac = data[6:12]
udp_offset = 14
ethertype = data[12:14]
if ethertype == [0x81, 0x00]: # 802.1Q VLAN-tagged
    udp_offset += 4
udp_pkt = data[udp_offset:]

一些注意事项:

  • Ethertype 值 0x88a8 表示 802.1ad QinQ 或“堆叠 VLAN”,需要适当处理才能正确找到 UDP 数据。
  • 在大多数 Linux 系统上,您需要root(或有CAP_NET_RAW能力)这样做。不确定您在 Windows 上需要什么,但假设类似。
  • 在实践中,这将是一个消防软管,因为它将接收所有UDP 数据包。您可以自己解析 UDP 标头以将其缩小到您感兴趣的范围内,或者(在 Linux / BSD 等上)调查 Berkeley Packet Filter 以让内核为您执行此操作。后者的 CPU 效率更高,但实施起来相当痛苦。
  • 建议 ARP 或类似的答案可能会做你想要的,但他们可能不会。他们会告诉你你的操作系统在 IP 地址和 MAC 之间有什么关联;这对于第 2 层协议、多播、广播等或响应 ARP 请求的内容无济于事。
于 2021-02-12T16:35:07.567 回答
0

我不知道如何在 python 中做到这一点,但可以获得 MAC 地址。例如,通过使用 tcpdump 我将所有数据包放入文件中:

sudo tcpdump -i enp0s31f6 -w file_name port 6665

然后在python中阅读它:

       packetlist = rdpcap("./file_name")
       for pkt in packetlist:  
       print pkt.src, pkt.load

你可以看到mac地址

编辑:我找到了一种方法:在函数 sniff 的帮助下用 scapy 嗅探所有包,然后过滤包以仅获取您需要的内容。例如,您可以在我的项目中使用 mac 地址:

sniff(prn=self._pkt_callback, store=0)

def _pkt_callback(self, pkt):
    if not self.sniffer_on:
         return
    if Ether not in pkt or pkt[Ether].type != 0x800:
        return
    if pkt[IP].proto != 17: # 17 means UDP package
        return
    if pkt[UDP].dport != 6665:
        return

    print pkt.src, pkt.load    #src is mac address
于 2017-09-03T15:23:00.557 回答