Make ARP request on python
Asked Answered
D

2

6

I'm trying to make ARP request on python. My code:

import socket
from struct import pack
from uuid import getnode as get_mac

def main():
    dest_ip = [10, 7, 31, 99]
    local_mac = [int(("%x" % get_mac())[i:i+2], 16) for i in range(0, 12, 2)]
    local_ip = [int(x) for x in socket.gethostbyname(socket.gethostname()).split('.')]

    sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.SOCK_RAW)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    sock.bind(('', 0))

    ARP_FRAME = [
        pack('!H', 0x0001), # HRD
        pack('!H', 0x0800), # PRO
        pack('!B', 0x06), # HLN
        pack('!B', 0x04), # PLN 
        pack('!H', 0x0001), # OP
        pack('!6B', *local_mac), # SHA
        pack('!4B', *local_ip), # SPA
        pack('!6B', *(0x00,)*6), # THA
        pack('!4B', *dest_ip), # TPA
    ]
    print(ARP_FRAME)
    sock.sendto(b''.join(ARP_FRAME), ('255.255.255.255', 0))
    sock.close()

if __name__ == "__main__":
    main()

When I execute this code, Wireshark does not catch any packets. I think problem in socket. When I do socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.SOCK_RAW) I get AttributeError: module 'socket' has no attribute 'AF_PACKET'. What am I doing wrong and how fix it?

OS X 10.11.3

Degrading answered 11/2, 2016 at 19:11 Comment(9)
Out of curiosity, is there any reason you're not using scapy?Merat
The layer-2 frame is a standard ethernet frame with a broadcast destination MAC address (FFFF.FFFF.FFFF) and the ARP ethertype (0x0806). The layer-3 packet with be an ARP request. See tcpipguide.com/free/t_ARPMessageFormat.htm for the ARP packet format.Endstopped
@Merat This is home assignment for "Computer Networks" course.Degrading
If you take a look at an ARP 'packet,' you'll see that it doesn't have a destination IP address because it is a Layer 2 Frame, not a packet. Ex: i.gyazo.com/e33183815d544a7eadb86da3e14373a4.png Your packets are being sent, but are NOT formatted correctly. i.gyazo.com/8b03adeb2db7fed565ca8f9b945cedcb.pngMerat
@Merat I change packet structure according to tcpipguide.com/free/t_ARPMessageFormat.htm. Here new structure gist.github.com/yutkin/1781aa574126ddb2ff65, but it does not work.Degrading
Why are you sending anything to 255.255.255.255? That makes no sense since this is not an IP packet. The frame is sent to the broadcast MAC address, and the ARP (not IP) packet contains the destination IP address to be resolved.Endstopped
@RonMaupin I should set some address for sendto method. Is there another ways for sending?Degrading
I will explain the way it works, and let you decide how to implement it since it is your homework. You need to create an ARP packet (not an IP packet) for the ARP request which includes the source and destination IP addresses, and the source MAC address. You need to encapsulate the packet in an ethernet frame which has the destination MAC address as the broadcast (FFFF.FFFF.FFFF) address, the source MAC address, and the ethertype set to ARP (0x0806). The frame then gets serialized and put on the wire. You should refer to RFC 826 which has the algorithms.Endstopped
@RonMaupin I understand about arp frame! I can't understand how to send it in Python! I can't use raw socket on OS X.Degrading
M
7

socket.AF_INET is a socket for IP packets. Since ARP is Ethernet, it won't work this way, you need access to the Ethernet layer.

On Linux, you can use:

s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(3))

with s being any variable you use to assign the socket to.

To send the packet, you should bind the interface with

s.bind(("eth0", 0))

Where "eth0" is the network-interface name.

After that, you can send the packet with

s.send(packet)

with packet being your payload as bytestring.

The

AttributeError: module 'socket' has no attribute 'AF_PACKET'

is saying, that AF_PACKET is not implemented on your platform. Unfortunately Some platforms don't provide access to the low-level network layer, this is true for windows, and may be true for OS X. At least, even on linux, you need root privileges to access the low-level networking, otherwise you'll get an access denied error.

An Idea to get access to the low-level networking via Python is to use a Virtual Machine, like Virtualbox, and run a linux guest with it.

Megara answered 30/5, 2017 at 16:45 Comment(1)
Confirming "AttributeError: module 'socket' has no attribute 'AF_PACKET'" on MacOS. Actually AF_PACKET is Linux specific, on BSD-like systems it works a bit different: https://mcmap.net/q/1467037/-af_packet-on-osxBennet
H
2

FTR, to work around this issue you can use Scapy. It will use:

  • AF_PACKET or libpcap on unix
  • BPF on BSD
  • Winpcap/Npcap on Windows

to access the raw layer in each case, which makes it cross platform.

Hospitalize answered 23/9, 2019 at 16:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.