6.3 动态主机配置协议DHCP
举例说明 DHCP 的作用

如图所示,有这样一个网络拓扑,我们应该给网络中的各主机设置怎样的网络相关配置信息,才能使他们可以正常访问网络中的Web服务器。根据我们之前课程所介绍过的相关知识可知,需要给网络中的各主机正确配置 IP 地址、子网掩码、默认网关、 DNS 服务器的网络相关配置信息。例如,这是我们给该主机手工配置的网络相关配置信息,这是我们给另一台主机手工配置的网络相关配置信息。如果网络中的主机数量比较多,则这种手工配置的工作量就比较大,并且容易出错。

如果我们给网络中添加一台 DHCP 服务器,在该服务器中设置好可为网络中其他各主机配置的网络配置信息。网络中各主机开机后自动启动 DHCP 程序,向 DHCP 服务器请求自己的网络配置信息,这样网络中的各主机就都可以从 DHCP 服务器自动获取网络配置信息,而不用手工参与。
举例说明 DHCP 的工作过程
假设网络中有两台 DHCP 服务器和多台用户主机,为了简单而有效的描述 DHCP 的工作过程,我们画出网络中的这两台 DHCP 服务器和一台用户主机。

DHCP 使用客户/服务器方式
在 DHCP 服务器上运行 DHCP 服务器进程,也可简称为 DHCP 服务器。
在用户主机上运行 DHCP 客户进程,也可简称为 DHCP 客户。
DHCP 是 TCP/IP 协议体系应用程中的协议,它使用运输层的 UDP 所提供的服务,也就是说, DHCP 报文在运输层会被封装成为UDP用户数据报。DHCP服务器使用的UDP端口是67, DHCP客户使用的UDP端口是68。这两个UDP端口都是熟知端口,封装有DHCP报文的UDP用户数据报在网络层会被封装成IP数据报,然后再根据所使用的网络接口封装成相应的数据链路层的帧进行发送,例如封装成以太网帧。
为了简单起见,在后续描述过程中,除非有特别需要,否则我们将不再每次描述 DHCP 报文逐层封装的过程。
下面我们来看看 DHCP 客户与 DHCP 服务器的交互过程。

当启用主机的 DHCP 后, DHCP 客户将广播发送DHCP 发现报文,封装该报文的 IP 数据报的源IP地址为0.0.0.0,这是因为主机目前还未分配到 IP 地址,因此使用该地址来代替。目的IP地址为广播地址255.255.255.255。之所以进行广播发送,是因为主机现在并不知道网络中有哪几个 DHCP 服务器,他们的IP地址各是什么。由于是广播的 IP 数据报,因此网络中的所有设备都会收到该 IP 数据报,并对其层层解封。解封出封装有 DHCP 发现报文的 UDP 用户数据报。
对于 DHCP 客户,其应用层没有监听该 UDP 用户数据报的目的端口 67 的进程,也就是 DHCP 服务器进程,因此无法交付 DHCP 发现报文,只能丢弃。而对于 DHCP 服务器,其应用层始终运行着 DHCP 服务器进程,因此会接受该 DHCP 发现报文并作出响应。
DHCP 报文的格式比较复杂,对于 DHCP 发现报文,我们只需要知道其内部封装有事务 ID 和 DHCP 客户端的MAC地址即可。
DHCP 服务器收到 DHCP 发现报文后,根据其中封装的 DHCP 客户端的 MAC 地址来查找自己的数据库,看是否有针对该 MAC 地址的配置信息。如果有,则使用这些配置信息来构建并发送 DHCP 提供报文;如果没有,则采用默认配置信息来构建并发送 DHCP 提供报文。
封装该报文的 IP 数据报的源IP地址为 DHCP 服务器的 IP 地址,目的 IP 地址仍为广播地址。仍然使用广播地址的原因是主机目前还没有配置 IP 地址,为了使主机可以收到,只能发送广播。这样一来,网络中的所有设备都会收到该 IP 数据报,并对其层层解封出封装有 DHCP 提供报文的 UDP 用户数据报,对于 DHCP 服务器,其应用层没有监听该 UDP 用户数据报目的端口 68 的进程,也就是 DHCP 客户进程,因此无法交付 DHCP 提供报文,只能丢弃。而对于 DHCP 客户,其应用层运行着 DHCP 客户进程,因此会接受该 DHCP 提供报文并作出相应处理。
DHCP 客户会根据 DHCP提供报文中的事务 ID 来判断该报文是否是自己所请求的报文。换句话说,如果该事务 ID 与自己之前发送的 DHCP 发现报文中封装的事物 ID 相等,就表明这是自己所请求的报文,就可以接受该报文,否则就丢弃该报文。DHCP 提供报文中还封装有配置信息,例如 IP 地址、子网掩码、地址租期、默认网关、 DNS 服务器等。
需要注意的是, DHCP 服务器从自己的 IP 地址池中挑选待租用给主机的 IP 地址时,会使用 ARP 来确保所选 IP 地址未被网络中其他主机占用。

在本例中, DHCP 客户会收到两个 DHCP 服务器发来的 DHCP 提供报文, DHCP 客户从中选择一个,一般来说,选择先到的那个,并向所选择的DHCP服务器发送 DHCP 请求报文,封装该报文的 IP 数据报的源IP地址仍为0.0.0.0,因为此时 DHCP 客户才从多个 DHCP 服务器中挑选一个作为自己的 DHCP 服务器。他首先需要征得该服务器的同意,之后才能正式使用向该 DHCP 服务器租用的 IP 地址。目的 IP 地址仍为广播地址255.255.255.255。这样做的目的是不用向网络中的每一个 DHCP 服务器单播发送 DHCP 请求报文,来告知他们是否请求他们作为自己的 DHCP 服务器。DHCP 请求报文中封装有事务ID、 DHCP 客户端的MAC地址、接受的租约中的 IP 地址、提供此租约的 DHCP 服务器端的 IP 地址等信息。

在本例中,假设 DHCP 客户选择 DHCP服务器 1 作为自己的 DHCP服务器,并且 DHCP服务器 1 接受该请求,于是 DHCP服务器 1 给 DHCP 客户发送 DHCP确认报文,封装该报文的 IP 数据报的源 IP 地址为 DHCP 服务器 1 的 IP 地址,目的 IP 地址仍为广播地址。 DHCP 客户收到该确认报文后,就可以使用所租用到的 IP 地址了。需要注意的是,在使用租用到的 IP 地址之前,主机还会使用 ARP 检测该 IP 地址是否已被网络中其他主机占用,若被占用, DHCP 客户会给 DHCP服务器发送 DHCP 谢绝报文来谢绝 IP地址租约,并重新发送 DHCP 发现报文;若未被占用,则可以使用租约中的 IP 地址与网络中的其他主机通信了。

当租用期过了一半时, DHCP 客户会向 DHCP服务器发送 DHCP 请求报文来请求更新租用期,封装该报文的 IP 数据报的源 IP 地址为 DHCP 客户之前租用到的 IP 地址,目的 IP 地址为 DHCP 服务器 1 的地址。 DHCP 服务器若同意,则发回 DHCP 确认报文,这样 DHCP 客户就得到了新的租用期;DHCP 服务器若不同意,则发回 DHCP 否认报文,这时 DHCP 客户必须立即停止使用之前租用的 IP 地址,并重新发送 DHCP 发现报文来重新申请 IP 地址。 DHCP 服务器若未作出响应,则在租用期过了 87. 5% 时,DHCP 客户必须重新发送 DHCP 请求报文,然后继续等待 DHCP 服务器可能作出的反应。若 DHCP 服务器未作出反应,则当租用期到期后, DHCP 客户必须立即停止使用之前租用的 IP 地址,并重新发送 DHCP 发现报文来重新申请 IP 地址。
DHCP 客户可以随时提前终止 DHCP 服务器所提供的租用期,这时只需要向 DHCP 服务器发送 DHCP 释放报文段即可。

综上所述(看左侧红色方框),这部分是 DHCP 客户寻找 DHCP服务器,这部分是 DHCP服务器向 DHCP 客户提供IP地址租用,这部分是 DHCP 客户接受 IP 地址租约,这部分是 DHCP 服务器确认 IP 地址租约,这部分是 DHCP 客户进行 IP 地址续约。这部分是DHCP客户可以随时解除 IP 地址租约。
需要注意的是, DHCP服务器在给 DHCP客户挑选IP地址时,使用ARP来确保所挑选的 IP地址未被网络中其他主机占用,而 DHCP 客户在使用所租用的 IP 地址之前,也会使用 ARP 来检测该 IP 地址是否已被网络中其他主机占用。
DHCP中继代理

如图所示,有这样一个网络拓扑,请大家思考一下,该网络中的各主机是否可以通过 DHCP 来自动获取到网络配置信息?答案是否定的。原因是该网络中的主机广播发送 DHCP 发现报文,但该广播报文不会被路由器转发,而是丢弃。
解决方法是给该路由器配置 DHCP 服务器的 IP 地址,并使之成为 DHCP 中继代理,这样该网络中的各主机就可以通过 DHCP 来自动获取到网络配置信息了。当该路由器收到广播的DHCP发现报文后,会将其单播转发给DHCP服务器。DHCP 客户和 DHCP 服务器通过该路由器的后续交互过程我们就不再赘述了。

使用 DHCP 中继的主要原因是,我们并不愿意在每一个网络上都设置一个 DHCP 服务器,因为这样会使 DHCP 服务器的数量太多。
本节小结
