Skip to content

Instantly share code, notes, and snippets.

@SupraJames
Created January 11, 2018 10:42
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save SupraJames/779475fefb6dfe7af315a68f03fe63dd to your computer and use it in GitHub Desktop.
Save SupraJames/779475fefb6dfe7af315a68f03fe63dd to your computer and use it in GitHub Desktop.
ARP responder using Python / scapy
# 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)
@acobo
Copy link

acobo commented Jan 13, 2018

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.

@bensuffolk
Copy link

bensuffolk commented Jan 14, 2018

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

@sveip
Copy link

sveip commented Feb 16, 2021

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?

@sveip
Copy link

sveip commented Feb 16, 2021

Quick update, it seems to work with this fix: 'who-has' instead if ARP.who_has

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment