-
-
Save SupraJames/779475fefb6dfe7af315a68f03fe63dd to your computer and use it in GitHub Desktop.
# Horrible bodge for when ESP82xx devices are not responding to ARP requests any more. | |
# This script can run anywhere on the subnet. It listens for ARP requests and responds | |
# with the MAC address in macDict based on the IP address. | |
# | |
# Note that it will ONLY respond if the IP address is found in macDict below. | |
# | |
# Please be careful with this tool. If wrongly configured, network breakage could occur. | |
# | |
# Requires scapy (pip install scapy) and tcpdump. Running tcpdump usually requires root | |
# so this script will need to be run as root. | |
# | |
# TODO: It would be great if the script could be improved to only send a response if we do | |
# not see a response on the wire within a second or so. At the moment we are blindy assuming | |
# that the ARP response is not coming. This will involve a lot more logic to keep track of what | |
# ARP requests have come in, and if they have been answered or not. | |
from __future__ import print_function | |
from scapy.all import * | |
import time | |
# Your network broadcast address | |
broadcastNet = "192.168.100.255" | |
macDict = { "192.168.100.152" : "60:01:94:98:97:c6", | |
"192.168.100.149" : "68:c6:3a:a7:d3:40"} | |
# Use MAC address of this machine as source. If not eth0, change this: | |
myMAC = get_if_hwaddr('eth0') | |
def handle_packet(packet): | |
if packet[ARP].op == ARP.who_has: | |
#print("Someone is asking about " + packet.pdst) | |
#print(packet.summary()) | |
if packet.pdst in macDict: | |
print("Sending ARP response for " + packet.pdst) | |
reply = ARP(op=ARP.is_at, hwsrc=macDict[packet.pdst], psrc=packet.pdst, hwdst="ff:ff:ff:ff:ff:ff", pdst=broadcastNet) | |
go = Ether(dst="ff:ff:ff:ff:ff:ff", src=myMAC) / reply | |
sendp(go) | |
return | |
# Sniff for ARP packets. Run handle_packet() on each one | |
sniff(filter="arp",prn=handle_packet) |
I have tried this and am getting the following error:
root@hass:/usr/local/bin# python2 arp_responder.py Traceback (most recent call last): File "arp_responder.py", line 43, in <module> sniff(filter="arp",prn=handle_packet,store=0) File "/usr/local/lib/python2.7/dist-packages/scapy/sendrecv.py", line 620, in sniff r = prn(p) File "arp_responder.py", line 31, in handle_packet if packet[ARP].op == ARP.who_has: File "/usr/local/lib/python2.7/dist-packages/scapy/packet.py", line 817, in __getitem__ raise IndexError("Layer [%s] not found" % lname) IndexError: Layer [ARP] not found
Do you have any ideas what might be causing this error?
Fixed the problem (posted here for others)
$ sudo apt-get install tcpdump tcpreplay wireshark
Hi, thanks for the script. I do get this error though:
Traceback (most recent call last):
File "macfix.py", line 42, in <module>
sniff(filter="arp",prn=handle_packet)
File "/home/ps/.local/lib/python2.7/site-packages/scapy/sendrecv.py", line 1036, in sniff
sniffer._run(*args, **kwargs)
File "/home/ps/.local/lib/python2.7/site-packages/scapy/sendrecv.py", line 989, in _run
session.on_packet_received(p)
File "/home/ps/.local/lib/python2.7/site-packages/scapy/sessions.py", line 82, in on_packet_received
result = self.prn(pkt)
File "macfix.py", line 30, in handle_packet
if packet[ARP].op == ARP.who_has:
File "/home/ps/.local/lib/python2.7/site-packages/scapy/base_classes.py", line 254, in __getattr__
raise AttributeError(attr)
AttributeError: who_has
Maybe who_has
is not correct in recent tcp-dump?
Quick update, it seems to work with this fix: 'who-has'
instead if ARP.who_has
I have found an issue with this script, in a raspberry PI 2 it stops working after a few hours due to memory overflow, the process is killed with an "out of memory" error. I have solved it adding the following option in the last line:
sniff(filter="arp",prn=handle_packet,store=0)
It seems that the sniff function from scapy stores all the processed ARP packets.
apart from that, it works flawless and solved the connectivity problem I had with my esp8266 modules.
Thanks and regards!
Adolfo.