I have written a DHCP server code in python using Scapy that can sniff discovery messages and send an appropriate offer message with an IP for a client. I tried to insert another option in the packet regarding the DNS server IP, but it doesn't show up no matter what in the DHCP options in the packet. Can someone help?
DHCP Server Code
from time import sleep
from scapy.all import *
from scapy.layers.dhcp import BOOTP, DHCP
from scapy.layers.inet import UDP, IP
from scapy.layers.l2 import Ether, ARP
import random
requested_ips = {}
assigned_ips = {}
domain_ip = ""
# Function to check if an IP address is in use
def ip_in_use(ip):
arp_request = Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(op="who-has", pdst=ip)
arp_response = srp1(arp_request, timeout=1, verbose=0)
if arp_response is not None:
return True
else:
return False
# Define a function to handle DHCP requests
def handle_dhcp_request(pkt):
if DHCP in pkt and pkt[DHCP].options[0][1] == 1:
print("DHCP Discover received")
client_mac = pkt[Ether].src
# Generate a random IP address if no specific IP was requested
random_ip = "192.168.1." + str(random.randint(2, 254))
# Check if the requested IP address is already in use on network
while ip_in_use(random_ip):
print(f"Requested IP {random_ip} is already in use, offering random IP")
random_ip = "192.168.1." + str(random.randint(2, 254))
# Check if the IP address was already assigned by the DHCP server
while assigned_ips and random_ip in assigned_ips.values():
random_ip = "192.168.1." + str(random.randint(2, 254))
requested_ips[client_mac] = random_ip
offer = Ether(src=get_if_hwaddr(conf.iface), dst=client_mac)/ \
IP(src="192.168.1.1", dst=random_ip)/ \
UDP(sport=67, dport=68)/ \
BOOTP(op=2, yiaddr=random_ip, siaddr="192.168.1.1", giaddr="0.0.0.0", xid=pkt[BOOTP].xid)/ \
DHCP(options=[("message-type", "offer"),
("subnet_mask", "255.255.255.0"),
("router", "192.168.1.1"),
("lease_time", 86400),
"end"])
# Add DNS server IP to options
offer[DHCP].options.insert(4, ("domain_name_server", domain_ip))
# Send packet
print(offer[DHCP])
sleep(1)
sendp(offer, iface=conf.iface)
print(f"DHCP Offer sent with IP: {random_ip}")
# Create an IP address for the DNS server
domain_ip = "192.168.1." + str(random.randint(2, 254))
# Set up a sniffing filter for DHCP requests
sniff_filter = "udp and (port 67 or 68)"
# Start sniffing for DHCP requests
print("DHCP Server started.")
print(f"Domain IP: {domain_ip}")
sniff(filter=sniff_filter, prn=handle_dhcp_request)
I tried using "offer[DHCP].options.insert(4, ("domain_name_server", domain_ip))" or add ("domain_name_server", domain_ip) in the (options=[("message-type", "offer"), ("subnet_mask", "255.255.255.0"),("router", "192.168.1.1"),("lease_time", 86400), "end"]) but it didn't. I right after try to do "print(offer[DHCP])" and there are no bytes representing the domain name...
According to the Scapy DHCP module (BOOTP Class),
the parameter name is name_server
,
and not domain_name_server
.