DHCP工作原理
目前让设备使用IP地址的方法主要有两种:静态设置IP和动态分配IP地址。一些组织往往会使用静态设置IP地址的方法这就需要用户在网络中设定IP地址,,网关和DNS等信息。而更多情况下,人们使用的都是动态分配IP地址的方法。
DHCP的工作原理与流程
(1) DHCP客户端在局域网内发送一个DHCP Discover数据包,目的是发现能够给它提供IP地址的DHCP服务器端。
(2) 接收到DHCP Discover数据包的DHCP服务器端会向请求的DHCP客户端发送一个DHCP Offer数据包,其中包含了可以使用的IP地址。
(3) 如果DHCP 客户端接收到多个DHCP Offer数据包,那么只会处理最先收到的。然后DHCP客户端会广播一个DHCP Request数据包,声明自己选用的DHCP服务器端和IP地址。
(4) DHCP 服务器端在接收到DHCP客户端广播的DHCP Request数据包后,就会判断该数据包中的IP地址是否与自己的地址相同。如果相同,就会像DHCP客户端发送一个响应的DHCP ACK数据包。
使用Python程序模拟DHCP客户端
DHCP数据包与Scapy函数对应关系如图所示:
DHCP动态分配IP地址时,DHCP客户端与DHCP服务器端一共发送了4个数据包,我们的工作就是使用scapy来构造这些数据包。困难在于每个数据包都需要设置其中的Ether,IP,UDP,BOOTP,DHCP这5个协议的内容。
DHCP Discover 数据包的构造
DHCP采用UDP作为传输层协议,DHCP客户端发送请求消息到DHCP服务端的67号端口,DHCP服务器端回应应答消息给DHCP客户端的68号端口。DHCP客户端以广播的方式发送DHCP Discover数据包,现在我们就来构造一个DHCP Discover数据包,实现代码如下
import random
from scapy.all import *
from scapy.layers.inet import IP,Ether,UDP,ICMP
from scapy.layers.dhcp import DHCP,BOOTP
import binascii
from scapy.volatile import RandMAC
mac_random = str(RandMAC())
Ether_Discover = Ether(src=mac_random,dst="ff:ff:ff:ff:ff:ff")
IP_Discover = IP(src="0.0.0.0",dst="255.255.255.255")
UDP_Discover = UDP(sport=68,dport=67)
client_mac_id = binascii.unhexlify(mac_random.replace(':',''))
xid_random = random.randint(1,900000000)
BOOTP_Discover = BOOTP(chaddr=client_mac_id,xid=xid_random)
DHCP_Discover = DHCP(options=[("message-type","discover"),"end"])
Discover = Ether_Discover/IP_Discover/UDP_Discover/BOOTP_Discover/DHCP_Discover
sendp(Discover,iface="以太网 2")
print("
Sending DHCPDISCOVER on"+"以太网")
DHCP Offer 数据包的捕获与解析
由于整个DHCP通信过程需要4个数据包,因此DHCP客户端需要捕获并解析DHCP服务器端发送的DHCP Offer数据包,才能继续进行后面的过程,这里我们可以使用Wireshark等抓包工具捕获DHCP数据包。
DHCP Request 数据包的构造
from scapy.layers.dhcp import BOOTP,DHCP
from scapy.layers.inet import Ether,IP,ICMP,UDP
from scapy.all import *
import binascii
def detect_dhcp(pkt):
if DHCP in pkt:
if pkt[DHCP].options[0][1] ==2:
Ether_Request =Ether(src=pkt[Ether].dst,dst="ff:ff:ff:ff:ff:ff")
IP_Request=IP(src="0.0.0.0",dst="255.255.255.255")
UDP_Request=UDP(sport=68,dport=67)
BOOTP_Request=BOOTP(chaddr=pkt[BOOTP].chaddr,xid=pkt[BOOTP].xid)
DHCP_Request=DHCP(options=[("message-type",'request'),("server_id",pkt[DHCP].options[1][1]),("requested_addr",pkt[BOOTP].yiaddr),"end"])
Request=Ether_Request/IP_Request/UDP_Request/BOOTP_Request/DHCP_Request
sendp(Request,iface='以太网')
print(pkt[BOOTP].yiaddr+"正在分配")
if pkt[DHCP].options[0][1]==5:
print(pkt[BOOTP].yiaddr+"已经分配")
sniff(filter="src port 67",iface='以太网',prn=detect_dhcp,count=10)
``
暂无评论内容