Python arp sniffing raw socket no reply packets
Asked Answered
I

1

15

to understand the network concepts a bit better and to improve my python skills I am trying to implement a packet sniffer with python. I have just started to learn python, so the code could be optimized of course ;)

I have implemented an packet sniffer which unpacks the ethernet frame and the arp header. I want to make it with raw sockets because I want to understand every byte within those headers, so please no scapy help :)

The problem is, that I won´t get any arp reply packet. It´s always opcode 1 and I

Here is my source code:

import socket
import struct
import binascii

rawSocket = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.htons(0x0806))

while True:

    packet = rawSocket.recvfrom(2048)

    ethernet_header = packet[0][0:14]
    ethernet_detailed = struct.unpack("!6s6s2s", ethernet_header)

    arp_header = packet[0][14:42]
    arp_detailed = struct.unpack("2s2s1s1s2s6s4s6s4s", arp_header)

    print "****************_ETHERNET_FRAME_****************"
    print "Dest MAC:        ", binascii.hexlify(ethernet_detailed[0])
    print "Source MAC:      ", binascii.hexlify(ethernet_detailed[1])
    print "Type:            ", binascii.hexlify(ethernet_detailed[2])
    print "************************************************"
    print "******************_ARP_HEADER_******************"
    print "Hardware type:   ", binascii.hexlify(arp_detailed[0])
    print "Protocol type:   ", binascii.hexlify(arp_detailed[1])
    print "Hardware size:   ", binascii.hexlify(arp_detailed[2])
    print "Protocol size:   ", binascii.hexlify(arp_detailed[3])
    print "Opcode:          ", binascii.hexlify(arp_detailed[4])
    print "Source MAC:      ", binascii.hexlify(arp_detailed[5])
    print "Source IP:       ", socket.inet_ntoa(arp_detailed[6])
    print "Dest MAC:        ", binascii.hexlify(arp_detailed[7])
    print "Dest IP:         ", socket.inet_ntoa(arp_detailed[8])
    print "*************************************************\n"

could someone please explain me why I am getting no response packets just these?

OUTPUT:

****************_ETHERNET_FRAME_****************
Dest MAC:         ffffffffffff
Source MAC:       0012bfc87243
Type:             0806
************************************************
******************_ARP_HEADER_******************
Hardware type:    0001
Protocol type:    0800
Hardware size:    06
Protocol size:    04
Opcode:           0001
Source MAC:       0012bfc87243
Source IP:        192.168.2.1
Dest MAC:         000000000000
Dest IP:          192.168.2.226
*************************************************

Thanks so far! :)

Illaffected answered 25/6, 2014 at 17:47 Comment(2)
I don't think it's the ARP opcode per se. Your recvfrom() seems to only able to capture inbound packets, not outbound ones. In this case, the opcode 2 (ARP reply) goes outbound, and it's not captured.Trahern
If you run your script and have your machine send an ARP ping, instead, you'll only see the opcode 2 (ARP reply) and none of the original outbound ping.Trahern
T
16

I think you need to specify socket protocol number 0x0003 to sniff everything, and then filter out non-ARP packets after the fact. This worked for me:

import socket
import struct
import binascii

rawSocket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003))

while True:

    packet = rawSocket.recvfrom(2048)

    ethernet_header = packet[0][0:14]
    ethernet_detailed = struct.unpack("!6s6s2s", ethernet_header)

    arp_header = packet[0][14:42]
    arp_detailed = struct.unpack("2s2s1s1s2s6s4s6s4s", arp_header)

    # skip non-ARP packets
    ethertype = ethernet_detailed[2]
    if ethertype != '\x08\x06':
        continue

    print "****************_ETHERNET_FRAME_****************"
    print "Dest MAC:        ", binascii.hexlify(ethernet_detailed[0])
    print "Source MAC:      ", binascii.hexlify(ethernet_detailed[1])
    print "Type:            ", binascii.hexlify(ethertype)
    print "************************************************"
    print "******************_ARP_HEADER_******************"
    print "Hardware type:   ", binascii.hexlify(arp_detailed[0])
    print "Protocol type:   ", binascii.hexlify(arp_detailed[1])
    print "Hardware size:   ", binascii.hexlify(arp_detailed[2])
    print "Protocol size:   ", binascii.hexlify(arp_detailed[3])
    print "Opcode:          ", binascii.hexlify(arp_detailed[4])
    print "Source MAC:      ", binascii.hexlify(arp_detailed[5])
    print "Source IP:       ", socket.inet_ntoa(arp_detailed[6])
    print "Dest MAC:        ", binascii.hexlify(arp_detailed[7])
    print "Dest IP:         ", socket.inet_ntoa(arp_detailed[8])
    print "*************************************************\n"

Sample output using arpping broadcast from the same host and its reply:

****************_ETHERNET_FRAME_****************
Dest MAC:         ffffffffffff
Source MAC:       000c29eb37bf
Type:             0806
************************************************
******************_ARP_HEADER_******************
Hardware type:    0001
Protocol type:    0800
Hardware size:    06
Protocol size:    04
Opcode:           0001
Source MAC:       000c29eb37bf
Source IP:        192.168.16.133
Dest MAC:         ffffffffffff
Dest IP:          192.168.16.2
*************************************************

****************_ETHERNET_FRAME_****************
Dest MAC:         000c29eb37bf
Source MAC:       005056f37861
Type:             0806
************************************************
******************_ARP_HEADER_******************
Hardware type:    0001
Protocol type:    0800
Hardware size:    06
Protocol size:    04
Opcode:           0002
Source MAC:       005056f37861
Source IP:        192.168.16.2
Dest MAC:         000c29eb37bf
Dest IP:          192.168.16.133
*************************************************
Trahern answered 25/6, 2014 at 18:39 Comment(3)
Ok, thank you! This is definitely working! Now I have to analyze this behavior! Thanks!Illaffected
Thanks for this! How did you know that protocol 0x0003 would sniff everything? I'm reading the "Assigned Internet Protocol Numbers" document and it says number 3 is GGP - Gateway-to-Gateway.Stonefish
The third parameter's (proto) semantic actually depends on the AF_* family in the first parameter. For AF_PACKET, protocol 0x3 means "all Ethernet frames" or ETH_P_ALL in Linux headers.Trahern

© 2022 - 2024 — McMap. All rights reserved.