Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Raw Socket to Ethernet Interface (Windows)

I'm trying to create a DHCP Server and the first step is for me to send packets through my ethernet port. I'm trying to send packets to my Ethernet interface and having an error popping up.

The code is below.

import socket

def sendeth(src, dst, eth_type, payload, interface = "eth0"):
  """Send raw Ethernet packet on interface."""

  assert(len(src) == len(dst) == 6) # 48-bit ethernet addresses
  assert(len(eth_type) == 2) # 16-bit ethernet type

  #s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
  s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)

  # From the docs: "For raw packet
  # sockets the address is a tuple (ifname, proto [,pkttype [,hatype]])"
  s.bind((interface, 0))
  return s.send(src + dst + eth_type + payload)

if __name__ == "__main__":
  print("Sent %d-byte Ethernet packet on eth0" %
    sendeth("\xFE\xED\xFA\xCE\xBE\xEF",
            "\xFE\xED\xFA\xCE\xBE\xEF",
            "\x7A\x05",
            "hello"))

I was having issues with the way the socket was being created. AF_PACKET is not recognized so I'm assuming that only works for Linux. I commented it out and added a new line below it. I ran it again and I started getting an error shown below.

Traceback (most recent call last):
  File "eth.py", line 27, in <module>
    "hello"))
  File "eth.py", line 19, in sendeth
    s.bind((interface, 0))
  File "C:\Python27\lib\socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
socket.gaierror: [Errno 11001] getaddrinfo failed

Does anyone know why this is happening?

like image 885
Sam Avatar asked Oct 18 '25 15:10

Sam


2 Answers

As said multiple times already, ETH_P_ALL is not implemented on Windows, due to Win32 limitations. The alternative is called Winpcap (more recently Npcap), which sets up Windows to access such low-level things (it adds an extra driver)

What you can do then is use a Winpcap/Npcap based library such as Scapy, to access Raw low-level sockets. This requires to install Npcap (or Winpcap) on the computer.

Then you can either use the library as-is (it has lots of capabilities of handling packets), or if you want to have access to the raw data

from scapy.all import *
IFACES.show() # let’s see what interfaces are available. Windows only
iface = <<"full iface name">> or <<conf.ifaces.dev_from_index(12)>> or <<conf.ifaces.dev_from_pcapname(r"\\Device_stuff")>>
socket = conf.L2socket(iface=iface)
# socket is now an Ethernet socket
### RECV
packet_raw = socket.recv_raw()[1]  # Raw data
packet_decoded = socket.recv() # Using the library (also contains things like sent time...)
### SEND
socket.send(b"\x00......"). # send raw data
socket.send(Ether()/IP(dst="www.google.com")/TCP()/Raw(load=b"data")) # use library

Thankfully this is cross-plateform.

like image 179
Cukic0d Avatar answered Oct 20 '25 06:10

Cukic0d


DHCP is a UDP protocol. You shouldn't need a raw socket to implement a DHCP server.

Use an AF_INET/SOCK_DGRAM socket, and bind to address 255.255.255.255 in order to implement your server.

like image 20
Gil Hamilton Avatar answered Oct 20 '25 04:10

Gil Hamilton