Sending DHCP Open using python scapy

I am new to python and am learning some networking programs, I want to send a DHCP packet through my interface to my DHCP server and expect some response from it. I tried several methods for building packages, such as structs and ctypes, and ended up using scapy. Here I can send a DHCP packet, but could not get any response from the DHCP server (analyzed using wirehark and tcpdump). My packet looked the same as the original DHCP packet, but received no response. Here is my code

import socket from scapy.all import * def main(): if len(sys.argv)<3: print " fewer arguments." sys.exit(1) else: tap_interface = sys.argv[1] src_mac_address = sys.argv[2] ethernet = Ether(dst='ff:ff:ff:ff:ff:ff',src=src_mac_address,type=0x800) ip = IP(src ='0.0.0.0',dst='255.255.255.255') udp =UDP (sport=68,dport=67) fam,hw = get_if_raw_hwaddr(tap_interface) bootp = BOOTP(chaddr = hw, ciaddr = '0.0.0.0',xid = 0x01020304,flags= 1) dhcp = DHCP(options=[("message-type","discover"),"end"]) packet = ethernet / ip / udp / bootp / dhcp fd = open('/dev/net/tun','r+') TUNSETIFF = 0x400454ca IFF_TAP = 0x0002 IFF_NO_PI = 0x1000 mode = IFF_TAP | IFF_NO_PI ifr = struct.pack('16sH', tap_interface, IFF_TAP | IFF_NO_PI) fcntl.ioctl(fd,TUNSETIFF,ifr) while True: sendp(packet, iface = tap_interface) time.sleep(10) if __name__ == '__main__': main() 

Are there other ways to achieve this? If yes, please indicate them as well. Thanks at Advance.

+7
python network-programming scapy dhcp
source share
3 answers

Solved! I had the same problem

The problem I'm thinking of relates to the srp () function, it cannot receive packets on port 68, but I created a new function with a new thread that sniffs BOOTP messages and displays the packet fields. you can simulate it:

sniff (iface = myiface, filter = "port 68 and port 67")

then send the packet using srp () or sendp () func :)

Note: I used the multithreading mechanism because my program sends messages and sniffs if there is an implicit DHCP server on the network.

+3
source share

I'm not sure that this will qualify as an answer, but we use scapy to simulate a DHCP server / client exchange, and the following work for us:

 discover = Ether(dst='ff:ff:ff:ff:ff:ff', src=cliMAC, type=0x0800) / IP(src='0.0.0.0', dst='255.255.255.255') / UDP(dport=67,sport=68) / BOOTP(op=1, chaddr=cliMACchaddr) / DHCP(options=[('message-type','discover'), ('end')]) 

The main difference between my code and yours is how the BOOTP header is defined. Maybe you could try defining my package and see if it works?

0
source share

Here is an example I made that gets the dhcp address and assigns it to the ip interface:

My rough POC, creating code for my project:

  #!/usr/bin/python from scapy.all import Ether,IP,UDP,DHCP,BOOTP,get_if_raw_hwaddr,get_if_hwaddr,conf,sniff,sendp from pyroute2 import IPDB from Queue import Empty from multiprocessing import Process, Queue, Manager from wpa_supplicant.core import WpaSupplicantDriver from twisted.internet.selectreactor import SelectReactor import threading import time import errno import sys import types import netifaces import dbus import json import re class PythonDHCPScanner: def change_ip(self,ipObject,netInterface): ipdb = IPDB() ips= ipdb.interfaces[self.get_interface(netInterface)] ipAddrs = ips.ipaddr.ipv4[0] ips.del_ip(ipAddrs['address'],ipAddrs['prefixlen']) ips.add_ip(ipObject['ipAddr'],24) ipdb.commit() ipdb.routes.add(dst="default",gateway=ipObject['router']) ipdb.commit() def queue_get_all(self): items = [] maxItems = 50 for numOfItemsRetrieved in range(0, maxItems): try: items.append(self.q.get_nowait()) except Empty, e: break return items def __init__(self): self.net_iface = netifaces.interfaces() def dhcp_print(self,pkt): self.q.put(str(pkt)) def get_interface(self,number): return str(self.net_iface[number].decode()) def get_interfaces(self): return self.net_iface def get_dhcp_object(self,interfaceNumber): self.q = Manager().Queue() c = Process(target=self.callSniffer,args=(interfaceNumber,)).start() time.sleep(0.1) p = Process(target=self.callPacket(interfaceNumber)).start() time.sleep(5) if c is not None: c.join() dhcp = {} for strPkt in self.queue_get_all(): try: pkt = Ether(strPkt) pkt.show() if pkt[Ether].dst == get_if_hwaddr(self.get_interface(interfaceNumber)): if pkt[DHCP]: if pkt.getlayer(DHCP).fields['options'][0][1] == 2: if pkt[IP]: dhcp['ipAddr'] = pkt[IP].dst for option in pkt.getlayer(DHCP).fields['options']: if option == 'end': break dhcp[option[0]] = option[1] print dhcp['router'] print dhcp['subnet_mask'] break except: continue return dhcp def callSniffer(self,interfaceNumber): inter = self.get_interface(interfaceNumber) conf.iface = inter print inter sniff(iface=inter,filter="udp",prn=self.dhcp_print, timeout=10) def callPacket(self,interfaceNumber): inter = self.get_interface(interfaceNumber) print inter fam,hw = get_if_raw_hwaddr(inter) macaddress= get_if_hwaddr(inter) conf.iface = inter ethernet = Ether(dst="ff:ff:ff:ff:ff:ff",src=macaddress,type=0x800) ip = IP(src="0.0.0.0",dst="255.255.255.255") udp = UDP(sport=68,dport=67) bootp = BOOTP(chaddr =hw,xid=0x10000000) dhcp = DHCP(options=[("message-type","discover"),("end")]) packet=ethernet/ip/udp/bootp/dhcp sendp(packet,iface=inter) # get dhcp object dave = PythonDHCPScanner() dhcpObject = dave.get_dhcp_object(3) # Pick interface number 3 on my box time.sleep(1) for dhcpKey in dhcpObject.keys(): print str(dhcpKey) + ":" + str(dhcpObject[dhcpKey]) time.sleep(1) dave.change_ip(dhcpObject,3) 
0
source share

All Articles