我们平时用电脑上网时,只要随手插入网线,就可以联网通信。我们知道主机通信需要IP地址,但是我们却很少主动配置IP地址就可以上网,这是为什么?这是因为有一个叫DHCP服务器的东西给你的电脑自动配置了一个IP地址


什么是DHCP

什么叫DHCP?


Dynamic Host Configuration Protocol,动态主机配置协议,为网络上的主机提供配置参数和网络地址


DHCP协议的前身是BOOTP协议,DHCP协议引入了“租约”的概念

DHCP协议由两部分组成:

  • 特定于主机的配置参数从DHCP服务器传送到主机的协议
  • 将网络地址分配给主机的机制

这里的特定于主机,指的应该是满足这个主机的配置参数,这些配置参数在这个主机中能够起作用

DHCP基于C/S模型,也就是客户端-服务器模式

这里的“服务器”是指通过DHCP提供初始化参数的主机,而“客户端”是指从DHCP服务器请求初始化参数的主机

所以DHCP的工作模式就是:指定的DHCP服务器主机分配网络地址并将配置参数传递给动态配置的客户端

DHCP有三种IP地址分配机制:

  • 自动分配

在“自动分配”中,DHCP为客户端分配一个永久IP地址

  • 动态分配

在“动态分配”中,DHCP将IP地址分配给客户端一段有限的时间(或直到客户端明确放弃该地址)

  • 手动分配

在“手动分配”中,客户端的IP地址由网络管理员分配,而DHCP仅用于将分配的地址传达给客户端

细品下这句话,“而DHCP仅用于将分配的地址传达给客户端”,也就是说在手动分配中,虽然网络管理员手动配置了客户端的IP地址,但是DHCP还是会分配IP地址并传达给客户端,只是客户端并不使用DHCP服务器分配的地址而已


原来手动配置IP地址也属于DHCP的分配机制,这是我没想到的


在这三种分配机制中,“动态分配”是唯一一种自动分配重用的不再需要的地址给客户端的机制

这里要如何理解?

如果某客户端A选择了动态分配,那么当它停用分配的IP地址时,此IP地址将被回收,且可以分配给选择动态分配的客户端B使用

因此,动态分配对于那些临时的客户端,或者IP地址资源比较有限需要共享的客户端来说,是一个很好的选择。对于那些永久连接到网络的新客户端,也可能是一个不错的选择


在某些IP地址资源稀缺的网络中,当旧的客户端停用时回收它们很重要


注意,DHCP不适用于配置路由器

DHCP协议

每一种协议的实现都是通过协议消息,那么DHCP消息格式如何呢

一文了解什么是DHCP协议_服务器

DHCP消息的所有字段描述如下:

字段

大小

描述

op

1字节

消息类型:1=BOOTREQUEST,2=BOOTREPLY

htype

1字节

硬件地址类型:对于以太网来说,该值为1

hlen

1字节

硬件地址长度:对于以太网来说,该值为6

hops

1字节

客户端设置为0,该字段是中继代理使用

xid

4字节

事务ID,客户端选择的随机数,客户端和服务器使用它来关联客户端和服务器之间的消息和响应

secs

2字节

由客户端填写,自客户开始地址获取或更新过程以来经过的秒数

flags

2字节

Flags

ciaddr

4字节

客户端IP地址;仅当客户端处于BOUND、RENEW或REBINDING状态并且可以响应ARP请求时才填写

yiaddr

4字节

‘your’(客户端)IP地址

siaddr

4字节

要在引导程序中使用的下一个服务器的IP地址;由服务器在DHCPOFFER、DHCPACK中返回

giaddr

4字节

中继代理IP地址,用于通过中继代理启动

chaddr

16字节

客户端硬件地址

sname

64字节

可选的服务器主机名,以空字符结尾的字符串

file

128字节

引导文件名,以空字符结尾的字符串;DHCPDISCOVER中的“通用”名称或null,DHCPOFFER中的完全限定目录路径名称

options

可变

可选参数字段

“flags”字段的格式如下:

一文了解什么是DHCP协议_网络协议_02

配置参数存储库

这是DHCP提供的第一个服务,为客户端提供网络参数的持久存储。DHCP持久存储的模型是DHCP服务为每个客户端存储一个key-value条目,其中key是一些唯一标识符(例如,IP子网号和子网内的唯一标识符),value包含配置客户端的参数

进一步的解释就是:


DHCP服务器存储着许多客户端的配置参数,每个客户端的配置参数是以一个键-值对的形式存储,其中键是能代表这个客户端的唯一标识符,值是这个客户端的配置参数


动态分配网络地址

这是DHCP提供的第二个服务,为客户端分配临时或永久的IP地址。动态分配的基本机制是:客户端请求使用某个地址一段时间。分配机制(DHCP服务器的集合)保证不会在请求的时间内重新分配该地址,并在每次客户端请求地址时尝试返回相同的网络地址

进一步的解释就是:


客户端向DHCP服务器请求使用某个IP地址一段时间,DHCP服务器的分配机制收到该请求后,不会把该地址重新分配给其他客户端,且此客户端每次请求该地址,都能返回相同的地址


这里的一段时间,就称为“租约”。而且客户端可以通过后续请求来延长租约

当客户端不再需要该地址时,客户端可能会发出消息将地址释放回服务器

客户可以通过请求无限租约来请求永久分配。即使在分配“永久”地址时,服务器也可能会选择提供冗长但非无限的租约,以允许检测客户端已退休的事实

上面这句话要怎么理解?


假如服务器提供无限租约,那么当客户端停用该地址时,服务器也不会检测客户端是否停用。因为提供无限租约就意味着服务器认为客户端会“永久”使用,虽然事实上客户端不大可能永远只用一个IP地址。所以服务器宁愿提供冗长但非无限的租约,这样服务器在租约结束时就可以检测客户端的状态,来确定客户端是否已退休,进而回收IP地址


Client-Server协议

上面提到,DHCP分配机制基于C/S模式,那么客户端和服务器在分配网络地址时的交互过程是什么样的呢?

客户端-服务器交互—分配网络地址

一文了解什么是DHCP协议_tcp/ip_03

一文了解什么是DHCP协议_客户端_04

  1. 客户端在其本地物理子网上广播DHCPDISCOVER消息。DHCPDISCOVER 消息可以包含建议网络地址和租用期限的值的选项。BOOTP中继代理可能会将消息传递到不在同一物理子网上的DHCP服务器


客户端因为没有IP地址,需要向服务器发送请求IP地址的DHCP消息。但是向哪个DHCP服务器发送,它不知道,所以需要先通过发送DHCPDISCOVER消息发现DHCP服务器。然而由于客户端本身就没有IP地址,而且不知道服务器的IP地址,所以要如何让DHCPDISCOVER消息被服务器接收呢,就可以通过广播的方式,把DHCPDISCOVER消息发送给广播域内的所有主机。但是如果广播域内没有DHCP服务器呢,就需要向外寻找,这时候就可以让BOOTP中继代理把消息转发到其他广播域的DHCP服务器上。那么DHCPDISCOVER消息里应该包含的内容有哪些,肯定要有IP地址,还有这个IP地址要租用的时间


  1. 每个服务器都可以响应DHCPOFFER消息,该消息在’yiaddr’字段中包含可用的网络地址(以及DHCP选项中的其他配置参数)。当分配一个新地址时,服务器应该检查提供的网络地址是否已经被使用,例如,服务器可以使用ICMP Echo Request探测提供的地址。服务器将DHCPOFFER消息发送到客户端,如果需要,使用BOOTP中继代理


所有接收到DHCPDISCOVER消息的服务器,都会发送DHCPOFFER消息给客户端来响应。DHCPOFFER消息里的‘yiaddr’字段就是分配给客户端的IP地址,当然DHCPOFFER消息里还会携带一些其他配置参数。但是,DHCP服务器在分配这个IP地址前,需要确认这个地址是否被其他主机使用,可以使用ICMP Echo Request消息里探测。如果是广播域外的服务器,它的DHCPOFFER消息需要经过BOOTP中继代理转发


  1. 客户端收到服务器发送的DHCPOFFER消息后,根据DHCPOFFER消息中提供的配置参数选择一台服务器来请求配置参数。客户端广播一个DHCPREQUEST消息,该消息必须包含“服务器标识符”选项以指示它选择了哪个服务器,并且可能包含指定所需配置值的其他选项。'requested IP address’选项必须设置为来自服务器的DHCPOFFER消息中的’yiaddr’值。如果客户端没有收到DHCPOFFER消息,则客户端超时并重新传输DHCPDISCOVER消息


DHCPOFFER消息提供的网络地址和配置参数,只是供客户端参考和选择,不是让客户端直接使用。客户端根据多个服务器提供的信息,选择其中的一个服务器,发送DHCPREQUEST消息来请求网络地址和配置参数。服务器提供了一个IP地址,客户端觉得可以,就请求这个IP地址,所以客户端的DHCPREQUEST消息里的‘requested IP address’选项必须是DHCPOFFER中的‘yiaddr’值。客户端是通过广播发送的DHCPREQUEST消息,这样可以确保它选择的服务器接收到,但是其他未被选择的服务器也能接收到,必须保证只有客户端选择的服务器接收并响应DHCPREQUEST消息,怎么办呢?就可以在这条消息里设置一个“服务器标识符”选项,这个选项就是客户端选择的服务器的标识符


  1. 服务器接收到广播DHCPREQUEST消息后,那些未被选择的服务器把此消息当成拒绝的通知,被选择的服务器用包含配置参数的DHCPACK消息进行响应。“客户端标识符”或“chaddr”和分配的网络地址的组合构成了客户端租约的唯一标识符,客户端和服务器都使用它来标识任何DHCP消息中引用的租约。DHCPACK消息中的任何配置参数都不应与DHCPOFFER消息中的配置参数冲突。服务器此时不应检查提供的网络地址。DHCPACK消息中的’yiaddr’字段填充了所选的网络地址。如果选择的服务器不能满足DHCPREQUEST消息(例如,请求的网络地址已经分配),服务器应该用DHCPNAK消息响应。服务器可以选择将在DHCPOFFER消息中提供给客户端的地址标记为不可用。如果服务器没有收到来自客户端的DHCPREQUEST消息,服务器应该将在DHCPOFFER消息中提供给客户端的地址标记为可用


只有被选择的服务器进行响应,通过发送包含配置参数的DHCPAKC消息。客户端和服务器都使用“客户端标识符”或“chaddr”和分配的IP地址的组合作为客户端租约的唯一标识。DHCPOFFER消息中的配置参数表明服务器可以提供这些参数,DHCPACK消息中的参数是正式提供给客户端的,这两条消息里的配置参数要相同。如果被选择的服务器发现客户端请求的地址已经被用了,这时候就需要给客户端回复DHCPAK消息。最后两句话的意思是当服务器发送DHCPOFFER时,表明这里面的地址可以提供给客户端使用,此时服务器可以把这个地址设置为不可用,这样其他客户端就没法使用了。但是如果迟迟没收到此客户端的请求消息,就要把这个地址释放给其他客户端,所以要设置为可用


这里还有一句话要注意,为什么在服务器提供IP地址的这一步,服务器不再检查网络地址了呢?

因为前面已经检查过了

  1. 客户端收到带有配置参数的DHCPACK消息,应该对参数进行最终检查(例如,网络地址的ARP),并注意DHCPACK消息中指定的租约期限。至此,客户端就配置好了。如果客户端检测到该地址已被使用(例如,通过使用ARP),客户端必须向服务器发送DHCPDECLINE消息并重新启动配置过程。客户端应该在重新启动配置过程之前至少等待十秒钟,以避免在循环的情况下出现过多的网络流量。如果客户端收到DHCPNAK消息,则客户端重新启动配置过程。如果客户端既没有收到DHCPACK也没有收到DHCPNAK消息,则客户端超时并重新发送 DHCPREQUEST消息。如果客户端在重传后既没有收到DHCPACK也没有收到DHCPNAK消息,则客户端恢复到INIT状态并重新开始初始化过程。客户端应该通知用户初始化过程失败并且正在重新启动


客户端在收到DHCPACK消息会一系列检查,并最终配置成功。在配置IP地址之前需要主动发送免费ARP检测该地址是否已经被使用。如果使用,需要发送DHCPDECLINE消息并重新启动配置过程等等,这里讲了各种客户端应该处理的情况


  1. 客户端可以选择通过向服务器发送DHCPRELEASE消息来放弃其对网络地址的租约。客户端使用其“客户端标识符”或“chaddr”和DHCPRELEASE消息中的网络地址来标识要释放的租约。如果客户端在获得租约时使用了“客户端标识符”,它必须在DHCPRELEASE消息中使用相同的“客户端标识符”


DHCPRELEASE消息是客户端用来放弃租约的消息,服务器通过租约的唯一标识符进行回收操作


所有的DHCP消息如下:

- DHCPDISCOVER

客户端广播以定位可用服务器

- DHCPOFFER

服务器对客户端的DHCPDISCOVER响应并提供配置参数

- DHCPREQUEST

  • 客户端向一个服务器请求参数并隐式拒绝其他服务器
  • 客户端确认先前分配的地址的正确性,例如系统重启
  • 客户端延长特定网络地址的租约

- DHCPACK

服务器发送给客户端配置参数,包括提交的网络地址

- DHCPNAK

服务器告知客户端的网络地址概念不正确(例如,客户端已移动到新子网)或客户端的租约已过期

- DHCPDECLINE

客户端告知服务器网络地址已在使用中

- DHCPRELEASE

客户端告诉服务器客户端放弃网络地址并取消剩余租约

- DHCPINFORM

客户端告知服务器,只询问本地配置参数;客户端已经有外部配置的网络地址

总结:


客户端先是定位所有可用的服务器(DHCPDISCOVER);服务器收到定位后把可用的网络地址和配置参数提供给客户端,以便客户端选择(DHCPOFFER);客户端选择其中一个服务器并拒绝其他服务器(DHCPREQUEST);被选择的服务器分配网络地址和配置参数给客户端(DHCPACK);客户端收到后做一系列的检查,没有问题后,配置完成


客户端-服务器交互—重用之前分配的网络地址

如果客户端记住并希望重用以前分配的网络地址,那么它们的交互过程如下:

一文了解什么是DHCP协议_DHCP_05

这里大概描述下流程:

  1. 客户端广播DHCPREQUEST消息
  2. 服务器发送DHCPACK消息响应。如果客户端的请求无效,比如客户端移到新的子网中,那么服务器用DHCPNAK消息响应
  3. 客户端收到DHCPACK消息检查无误后,配置完成