Finding the MAC address of the sender of a multicast UDP message in Python?
-
19-09-2019 - |
Question
I have some code that listens for "announcements" via UDP multicast. I can get the IP address of the sender, but what I really need is the MAC address of the sender (since the IP address can and will change).
Is there an easy way to do this in Python?
A code snippet is included for reference, but likely unnecessary.
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)
...
Solution
You cannot, in general, get the mac address. You might succeed using ARP on a LAN, but across the Internet it's not possible.
Consider the case where the packet you receive has the IP address of the sender's NATting router. The packet may have traversed any number of intermediate machines along the way, each of which have mac addresses, too. Whose responsibility should it be to support the kind of lookup you're after? For all the machines along the way, the sender's mac address is completely useless, so why bother supporting that kind of lookup?
And, btw, changing the mac address is trivial on many network cards, so using it as some kind of unique ID is not a wise idea.
OTHER TIPS
The protocol you need is ARP. Check this question/answer for details
I'm not sure that it is possible to get the sender's MAC address since the MAC address is a link level address and not a network level address like IP. The MAC address will change at each hop in the network as the packet containing the UDP message is routed from the sender to the receiver.
I don't know how to do it in python but it is possible to get MAC address. For example by using tcpdump I put all packets into file:
sudo tcpdump -i enp0s31f6 -w file_name port 6665
then in python read it with:
packetlist = rdpcap("./file_name")
for pkt in packetlist:
print pkt.src, pkt.load
you can see the mac address
edit: I found one way to do this: sniff all packages with scapy with the help of function sniff, then filter the packages to get only what you need. There you can use mac address for example from my project:
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