在Python中查找组播UDP消息发送者的MAC地址?

问题描述:

我有一些代码,通过UDP多播监听“通知”。我可以获取发件人的IP地址,但我真正需要的是发件人的MAC地址(因为IP地址可以并将会更改)。在Python中查找组播UDP消息发送者的MAC地址?

有没有一种简单的方法在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) 

...

+0

应该可以用'scapy'的L2插座虽然可能需要一些工作:http://www.secdev.org/projects/scapy /doc/usage.html – Pierz 2016-12-07 18:10:15

一般情况下,您无法获取mac地址。你可能在局域网上使用ARP成功,但在互联网上是不可能的。

考虑您收到的数据包具有发件人的NATting路由器的IP地址的情况。数据包可能沿途经过任意数量的中间机器,每个中间机器都有mac地址。应该支持你追求的那种查找的责任是谁?对于一路上的所有机器来说,发件人的mac地址是完全无用的,那么为什么还要支持这种查找呢?

而且,btw,changing the mac address在很多网卡上都是微不足道的,因此将它用作某种独特的ID并不是一个明智的想法。

+0

假设我不想获取原始发件人的MAC,而是传输UDP数据包的以太网数据包的“源MAC”。是否有可能使用标准的Linux设施?至少我可以在Windows上的Wireshark中获得这些信息。 – 2016-01-20 12:52:23

你需要的协议是ARP。请查看question/answer了解详情

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

我不知道如何在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地址

编辑: 我找到了一个办法要做到这一点: 借助函数嗅探嗅探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