DHCP协议分析
DHCP协议封装
DHCP协议是基于UDP层之上的应用,DHCP CLIENT将采用端口号68,DHCP SERVER采用端口号67,其报文内容的封装如下所示:
链路层头 IP头 UDP头 DHCP报文
其中:
链路层头:承载报文的链路层信息头。
IP头:标准IP协议头,IPV4中长度为20bytes,包括SrcIp,DstIp等信息。
UDP头:8个bytes,包括SrcPort,DstPort,报文长度及UDP校验和等信息。
DHCP报文:具体的DHCP报文内容。
由于DHCP协议是让终端获取IP 地址的协议,所以终端是没有IP地址的。为了能够正常的收发DHCP报文,采取了如下措施:
a)、链路层的封装必须是广播形式,即让在同一物理子网中的所有主机都能够收到这个报文,在Ethernet_II格式的网络中,是DstMac为全1。
b)、由于终端没有IP地址,IP头中的SrcIp规定填为全0。
c)、当终端发出DHCP请求报文,并不知道DHCP SERVER的IP地址,因此IP头中的DstIp填为有限的子网广播IP——全1,保证DHCP SERVER的IP协议栈不丢弃这个报文。
d)、上面的措施保证了DHCP SERVER能够收到终端的请求报文,但仅凭链路层和IP层信息,DHCP SERVER无法区分出DHCP报文,因此终端发出的DHCP请求报文的UDP层中的SrcPort为68,DstPort为67,即DHCPSERVER通过端口号67来判断一个报文是否是DHCP报文。
DHCP报文格式
op:报文的操作类型,分为请求报文和响应报文,1为请求报文;2为响应报文。具体的报文类型在option字段中标识。
htype:硬件地址类型。
hlen:硬件地址长度。系统目前只对以太网支持,硬件地址长度固定为6。
hops:DHCP 报文经过的DHCP 中继的数目。DHCP 请求报文每经过一个DHCP中继,该字段就会增加1。
xid:由客户端软件产生的随机数,用于匹配请求和应答报文。
secs:客户端进入IP 地址申请进程的时间或者更新IP 地址进程的时间;由客户端软件根据情况设定。目前没有使用,固定为0。
flags:标志字段。第一个比特为广播响应标识位,用来标识DHCP 服务器响应报文是采用单播还是广播方式发送,0 表示采用单播方式,1 表示采用广播方式。其余比特保留不用。
ciaddr:DHCP客户端的IP地址。
yiaddr:DHCP服务器分配给客户端的IP地址。
siaddr:DHCP客户端获取IP地址等信息的服务器IP地址。
giaddr:DHCP客户端发出请求报文后经过的第一个DHCP中继的IP地址。
chaddr:DHCP客户端的硬件地址。
sname:DHCP客户端获取IP地址等信息的服务器名称。
file:DHCP服务器为DHCP客户端指定的启动配置文件名称及路径信息。
options:可选变长选项字段,包含报文的类型、有效租期、DNS 服务器的IP地址、WINS服务器的IP地址等配置信息。
分析流程图:
DHCP协议包含以下八种类型:
1:DHCPDISCOVER(0x01),此为Client开始DHCP过程的第一个报文
2:DHCPOFFER(0x02),此为Server对DHCPDISCOVER报文的响应
3:DHCPREQUEST(0x03),此报文是Slient开始DHCP过程中对server的DHCPOFFER 报文的回应,或者是client续延IP地址租期时发出的报文
4:DHCPDECLINE(0x04),当Client发现Server分配给它的IP地址无法使用,如IP 地址冲突时,将发出此报文,通知Server禁止使用IP地址
5:DHCPACK(0x05),Server对Client的DHCPREQUEST报文的确认响应报文,Client 收到此报文后,才真正获得了IP地址和相关的配置信息。
6:DHCPNAK(0x06),Server对Client的DHCPREQUEST报文的拒绝响应报文,Client 收到此报文后,一般会重新开始新的DHCP过程。
7:DHCPRELEASE(0x07),Client主动释放server分配给它的IP地址的报文,当Server 收到此报文后,就可以回收这个IP地址,能够分配给其他的Client。
8:DHCPINFORM(0x08),Client已经获得了IP地址,发送此报文,只是为了从DHCP SERVER处获取其他的一些网络配置信息,如route ip,DNS Ip等,这种报文的应用非常少见。
以上八种DHCP类型均包含以下特征值(在OpenDPI中,只需要确认当前检测的协议符合以下五个特征值,就认为当前协议是DHCP协议,并不需要确认具体是哪种DHCP协议类型。):
一、packet->payload_packet_len >= 244
//确认当前检测的数据包的payload区长度大于244
二、(packet->udp->source == htons(67)|| packet->udp->source == htons(68))
三、(packet->udp->dest == htons(67) || packet->udp->dest == htons(68))
/*
1)确认当前检测的报文的数据包的UDP包的目的端口为67或68。
2)sever的端口位67,client的端口位68。
*/
四、get_u32(packet->payload, 236) == htonl(0x63825363)
/*
1)#define get_u32(X,O) (*(u32 *)(((u8 *)X) + O))的目的是,从u8型X指针指向
的地址区域中,第O个地址开始取四个字节的内容。
2)htonl(u_long hostlong)将主机的无符号长整形数转换成网络字节顺序。
3)从任一DHCP协议类型的packet->payload区中第236位开始取四个字节,
确认Magic Cookie位的值为DHCP。
*/