0%

DHCP 主机动态配置协议详解

一、DHCP介绍

1. 简要介绍

DHCP 协议在我们日常生活中应该是最常见而又经常被忽略的一种协议了。当你走进一间屋子,手机自动连上了 WiFi,当你离开了屋子,又自动断开了 WiFi…… 这一系列的幕后都是DHCP协议在默默工作。

DHCP 协议(Dynamic Host Configuration Protocol)是一个基于UDP协议的局域网的网络协议。指的是由服务器控制一段 IP 地址范围,客户机登录服务器时就可以自动获得服务器分配的 IP 地址和子网掩码。

该协议的最大作用是动态的为加入网络的设备分配 IP 地址,在该协议出现前,IP 地址的分配基于静态模式,你把设备的 mac 地址手动在路由器设置,然后路由器自动生成一个 IP 与你的 mac 地址绑定起来。这种应用在有线网络时代可以适用,但在无线时代,每时每刻可能有不同的设备加入或离开网络,因此原有静态匹配 IP 的做法不再适合。

DHCP 协议的诞生就是为了迎合在无线情况下,网络内部连接设备不断变化的情况。它包含两部分,一是分配 IP 地址,二是支持客户端请求,服务器应答,使得两者之间有效交换配置信息。

DHCP 最重要功能显然是动态分配 IP 地址,当我们的设备连接上网络之后里面获得一个可用的 IP 地址,就得感谢该协议的执行,现在我们大多数设备都依靠 DHCP 来从路由器动态获得 IP

2. DHCP 的 IP 租借

DHCP 协议能够维护一个动态的 IP 池,根据设备加入和离开网络回收或分发可用 IP,它甚至能实现多个设备共享相同 IP。DHCP 协议的实现基于 UDP,需要 IP 的设备和具备分配 IP 能力的设备根据 DHCP 协议的方式封装数据包,然后通过 UDP 协议发送给对方。有了该协议后,我们上网时不再麻烦的去配置各种信息,设备和路由器之间相互通信后,自动配置好相应信息,我们只要等着配置完毕然后上网就行。

DHCP 支持三种地址分配方式,一种是手动分配,由管理员手动将指定 IP 地址分发给特定设备;第二种是自动分配,它从当前可用的 IP 地址池中选出一个,永久的分发给某一台特定设备;第三种是动态分配,它从 IP 地址池中选出一个分发给某台设备一段时间,时间到了后收回,或者设备离开网络后通知路由器主动收回,由此可见,第二种和第三种区别不大

使用动态分配方式时,管理员指定一系列可以分配的 IP,然后 DHCP 服务器会自动维护哪些 IP 已经分配,哪些 IP 可以使用。同时服务器指定分配的 IP 使用时长,一旦超时后,客户必须主动向服务器请求续租,例如上图就有对应按钮,或者请求重新从服务器获得一个新的 IP 地址,这个请求应答过程将是我们研究和实现的重点。

DHCP 协议动态分配 IP 的好处显而易见,首先是自动化,省却了管理员耗时耗力的维护,其次是集中管理,从服务器就可以得知IP的使用情况,由此有效防止 IP 冲突。而且还能实现地址的共享和重用,如果一台设备不活跃,例如关机或离开网络,协议可以及时收回 IP,分发给在网络中的其他设备。

在 DHCP 协议管理下,所有设备只能“租借” IP 而不能“拥有” IP。有租借就必须有管理,DHCP 协议的主要内容就在这里。租借时常根据设备的使用情况而定,作为服务器的设备租借时间必须很长,而对于手持设备而言,租借时间可以很短。在很多情况下,管理员为了防止 IP 被长时间无效占用,例如某台设备计划租借一个月,但它运行一天就关机了,那么这个 IP 就会在余下 29 天浪费掉,因此管理员会强制设备租借短时期,时期到了后再跟服务器请求延长租借期。

管理员一般把 IP 池划分为若干类别,不同类别对应不同租期,然后根据接入设备的类型赋予不同类别的IP。一旦租期抵达一半时,设备就开始于服务器协商以便延长租期。

下面是IP租借的流程图:

IP租借

上图描述了设备向 DHCP 服务器租借 IP 8 天流程,其中在第 4 天要与服务器协商续租。租借 IP 的设备需要保持两个时钟,时钟 T1 在租借期过了一半时触发,此时设备向服务器请求续租;如果续租不成功,第二个时钟在租期 87.5% 时触发,设备向另一个 DHCP 服务器发起租借 IP 的请求。我们后面用代码实现协议时,主要通过构造数据包完成上面所述流程。

DHCP 协议时典型的服务器客户端应用模式。需要 IP 的设备是客户端,分发 IP 的设备是服务器,两者通过互发消息完成一项任务。他们之间的交互可以由下图表达:

DHCP握手

类似于 TCP 的握手,但是又比 TCP 简单不少。

二、DHCP主机动态配置协议解析和数据包格式说明

1. 查看DHCP数据包

打开网络封包分析软件 WireShack,输入过滤条件 bootp.option.type == 53 (或者 dhcp.option.type == 53 也可),在命令行中输入 ipconfig/renew,表示续租 DHCP 服务器,我们获取这样的数据包:

DHCP数据包介绍

点开一个数据包,看到:

具体格式

我们看到 DHCP 协议数据包的组成格式为 IP数据包->UDP数据包->Boostrap Protocoal数据包(也就是DHCP数据包)

【注】Boostrap 是DHCP协议的前身,它叫主机静态配置协议。DHCP其实是它的扩展,将原来静态配置的过程动态化,于是配置起来更加灵活方便,只不过DHCP数据包的依然以Boostrap协议数据包为基础。

我们点开 DHCP 看看具体内容:

DHCP具体内容

通过观察,我们大概可以知道 DHCP 数据包大概有哪些字段,要了解这些字段的作用,我们还得充分了解协议的具体交互流程。DHCP 协议以客户端<->服务器的方式进行交互,整个过程由客户端主导,服务器被动回应,因此掌握客户端的运行状态,我们就可以掌握 DHCP 的协议交互流程。

2. DHCP流程

DHCP 在执行时维护了一个状态机,该状态机由八个状态组成。

客户端在运行时维护一个内部状态机,其运行过程如下:

  1. INIT 状态。客户端创建一个DHCPDISCOVER消息在局域网内广播,查询可用的 DHCP 服务器,然后进入SELECTING状态。
  2. SELECTING 状态。局域网内的DHCP收到广播消息后,发送DHCPOFFER消息,客户端会收到一个或多个 DHCP 服务器的回应,然后它从众多回应中选取一个服务器,向它发送DHCPREQUEST消息,然后进入REQUESTING状态。
  3. REQUESTING 状态。客户端向服务器发送 DHCPREQUEST 消息中包含了它对服务器的数据请求,例如可用IP地址以及各类配置参数,请求发送出去后它等待服务器回应。服务器会返回DHCPACK 消息,里面包含了客户端想要的可用IP以及配置参数等信息。
    收到消息后,客户端检测服务器返回的 IP 地址是否可用,可用的话进入使用状态并像上一节描述的那样设置两个超时时钟。如果客户端发现 IP 地址不可用,它向服务器发送 DHCPDECLINE消息,然后转入状态1。
    如果客户端从服务器收到的是DHCPNAK消息,它表示服务器拒绝向客户端提供服务,因此客户端重新进入状态1.
  4. INIT-REBOOT 状态。如果客户端已经租借到IP,它重启后进入该状态。此时它会向服务器发送 DHCPREQUEST 消息,重新确定它对IP的使用权,然后客户端进入 REBOOTING 状态,等待服务器反应。
  5. REBOOTING 状态。此时客户正在等待服务器返回确认消息,此时会有 3 种情况。一是客户端收到服务器发来的 DHCPACK 消息,表明可以继续使用它当前 IP,于是客户端进入 BOUND 状态;二是,客户端得到 DHCPACK 回应,然后发现它原来使用的 IP 在自己关机或重启时,被其他设备抢夺了,于是他想服务器发送 DHCPDECLINE 消息,然后进入状态 1;三是收到服务器发来的 DHCPNAK 消息,这表明服务器告诉客户端 IP 不能再继续使用,于是客户端进入状态 1.
  6. BOUND 状态。此时客户端得到可用IP地址,并进入使用状态。此时它启动两个时钟,T1 和 T2。当 T1 超时时,它进入状态 RENEWING。如果客户端主动要放弃使用当前 IP,它会向服务器发送 DHCPRELEASE 消息,然后进入状态 1.
  7. RENEWING 状态。此时客户端希望续租当前 IP,于是他想客户端发送 DHCPREQUEST 消息,然后等待服务器确认。此时客户端要面临三种情况,一是服务器返回 DHCPACK 消息,它可以继续使用当前 IP;二是收到 DHCPNAK 消息,服务器拒绝客户端继续租用当前 IP;三是客户端的 T2 时钟超时,客户端进入 REBINGDING 状态。
  8. REBIDING 状态。此时客户端无法继续续租原有 IP,于是它持续向局域网广播 DHCPREQUEST 消息,直到有服务器响应它为止。此时客户端又面临三种情况。一是有服务器向客户端返回 DHCPACK 消息,于是客户端可以使用新分配的 IP;二是服务器返回 DHCPNAK 消息,这表明服务器希望客户端重新启动租借流程,于是客户端进入 INIT 状态;第三是,在收到回应前,客户端当前租用的 IP 到期,它重新进入 INIT 状态。

为了简单起见,我们将以客户端的方式编写代码,上面的流程状态可以使用下图统一描述:

状态机

3. 字段详解

首先完成第一步,客户端向局域网广播消息,然后收到服务器应答。下面是 DHCP 消息的具体格式:

DHCP具体格式

上面的是前面抓包时对应的 DHCP 部分,依次解析各个字段:

  • op 字段 1 字节,它表明消息类型,请求消息使用数值1,回应消息使用数值2
  • HType 1 字节,它表明消息发送所使用的网络类型,由于我们默认使用互联网,因此它的值固定为 1
  • HLen 字段 1 字节,它表明设备硬件地址的长度,由于我们默认使用 mac 地址,因此该字段固定为 6
  • Hops 字段 1 字节,它表明数据包可以跨越几个不同网络,该字段的作用我们在前面 traceroute 程序中了解过,由于我们希望限制消息在当前局域网内流通,因此设置为 0
  • XID 字段 4 字节。它与 ICMP 消息中的 session 作用一样,用来标志一次对话过程
  • Secs 字段 2 字节。它用来表明客户端发出请求后等待的时间,一般该字段不常使用,我们将它固定为 0
  • Flags 字段 2 字节,取值 0 或 1,如果设置为 1,客户端要求服务器以广播的方式发送回应消息,因为此时客户端可能还没有 IP 地址
  • CIAddr 字段 4 字节,它存放客户端当前 IP 地址,如果客户端当前有 IP,而且进入状态 BOUND,RENEWING 状态,其他情况下统一设置为 0
  • YIAddr 字段 4 字节,这是服务器返回给客户端使用的IP
  • SIAddr 字段 4 字节,服务器 IP 地址,它有点特殊,这个 IP 是不一定是当前交互的服务器 IP,而是设备下次启动时去获取IP地址的服务器IP
  • GIAddr 字段 4 字节,网关 IP,当 DHCP 服务器不在本地局域网时,设备将通过该 IP 将数据包转发给处于另一个局域网的服务器,通常情况下使用不到
  • CHAddr 字段 16 字节,设备的硬件地址。由于我们默认设备使用 mac 地址,因此只使用到 6 个字节,其余 10 个字节用 0 填充
  • SName 字段 64 个字节,该字段用做 DHCP 服务器的字符串名称
  • File 字段 128 字节,该字段用于在设备和服务器间交换特定信息
  • Options 字段,可变长。该字段用于设备和服务器间交换多种配置信息

接下来我们看看 Options 字段,由于所有信息的交互都存储在该字段,因此我们需搞清楚它的结构。在该字段开始前是4个字节的 魔术字,固定为 99.130.83.99(十六进制:63 82 53 63),然后才是一系列 Option 数据结构,Option 数据结构组成如下。

option组成

每个 Option 由三字段组成,第一字段是 Code,用来表明当前 Option 类型,它有两个特殊值,一个是 0,它表示当前 Option 只有这一个字节,另一个特殊值是 255,它表示后续不再含有 Option结构体;第二字段是 len,用来标志数据段的长度;第三字段是 Data,用来存储数据。

由于 Option 结构体用于客户端与服务器进行数据交换,因此它的种类相当繁杂。