说明: 本文是以下文献相关内容的总结
[1] 《TCP/IP详解 卷1:协议》
[2] 《TCP/IP协议族 第4版》
[3] 《计算机网络 第5版》
DHCP(Dynamic Host Configuration Protocol),动态主机配置协议,该协议经常发挥的两大作用:一是为网络中不知道自己IP地址的主机分配IP地址,二是为网络中的无盘系统提供引导加载程序。
使用windows操作系统的用户经常会遇到连接网络的问题,也就是说我们如何将自己的主机连接到Internet呢?我们经常会配置一些连网信息,如下图所示:
从上图可以看出,要连上网,我们通常会包含4项基本信息:IP地址、子网掩码、默认网关和DNS首选服务器的IP地址。我们可以采用手动设置或自动获取的方式来获得IP地址,手动设置的方式采用的是BOOTP协议(引导程序协议),自动获取的方式则采用的是DHCP协议。由于DHCP是对BOOTP的加强版本,在针对静态主机配置时不仅兼容BOOTP协议,同时能够动态地提供IP地址,从这个角度来说,BOOTP协议可以认为是DHCP协议的一个淘汰版本。当然,并不是说DHCP协议完全更改了BOOTP协议,而应该说DHCP协议扩展了BOOTP协议。
MAC地址到IP地址的映射
就时间顺序而言,提供MAC地址-->IP地址映射的协议包括:RARP协议、BOOTP协议和DHCP协议。
RARP协议(Reverse Address Resolution Protocal):逆地址解析协议,RARP协议利用了数据链路层的广播服务,存在两个明显的缺点:第一、只能该请求主机所在的网络的中进行广播,因而每个网络上都必须有一台RARP服务器;第二、RARP只能提供IP地址,而不能提供其他信息(如子网掩码、默认网关和DNS服务器等),所以后来就提出了BOOTP协议。
BOOTP协议(BOOTstrap Protocol):引导程序协议,是一种C/S协议,克服了RARP协议的两个缺陷,具体表现为:(1)BOOTP协议是一个C/S程序,BOOTP服务器可以位于Internet的任何地方;(2)BOOT协议除了返回IP地址外,还提供其他配置信息(如子网掩码等),这些信息可以记录在BOOTP报文的选项部分。但是BOOTP协议的缺陷也很明显:BOOTP协议是一个静态配置协议。也就是说当客户请求自己的IP地址时,BOOTP服务器就会查找一张(MAC-->IP)的映射表,这种映射关系必须是事先设定好的。也就是说:BOOTP协议中,MAC地址和IP地址之间的绑定关系是静态的,是固定存放在一张表中,除非管理员更改这张表。所以后来就提出了现在耳熟能详的DHCP协议。
DHCP协议(Dynamic Host Configuration Protocal):动态主机配置协议。同BOOTP协议一样,DHCP协议也是基于C/S方式的,DHCP是BOOTP的继承者,并且能够兼容BOOTP。DHCP不仅能够处理静态配置(此时等同于BOOTP协议),而且能够处理动态配置。也就是说,在客户在查找其自己的IP地址时,DHCP服务器中(MAC-->IP)地址可以事先存在,也可以临时分配。换句话说:当客户发送DHCP请求报文时,DHCP服务器服务器先在其数据库中查找该计算机的配置信息。若找到,则返回找到的信息。若找不到,则从服务器的IP地址池中取一个地址分配给该计算机。
DHCP客户与服务器
DHCP客户与DHCP服务器可以在同一个网络中,也可以位于不同的网络中。
I.两者在同一个网络的通信
1)DHCP服务器在端口号为67的UDP端口发出被动打开的命令,等待客户请求;
2)DHCP客户在端口号为68(注意:这个端口号不是临时端口号,而是一个熟知端口号)的UDP端口发出主动打开命令,此时客户端使用0.0.0.0作为源IP地址,使用255.255.255.255(受限的广播地址)作为目的IP地址,源端口号为68,目的端口号为67;
3)服务器或者用广播报文(不常用),或者用单播报文(常用)响应这个客户请求。
II.两者在不同的网络之间的通信
当DHCP客户端与DHCP服务器位于不同的网络时,需要在DHCP网络中选择一个中继代理(可以是主机,也可以是路由器),中继代理知道DHCP服务器的单播地址。具体通信如下:
1)DHCP服务器在端口号为67的UDP端口发出被动打开的命令,等待客户请求;
2)DHCP客户在客户端为68的UDP端口发出主动打开的命令,此时客户端使用0.0.0.0作为源IP地址,使用255.255.255.255作为目的地址,源端口号为68,目的端口号为67;
3)中继代理收到客户请求分组后,就把它封装成一个单播数据报,并且把此请求发送给DHCP服务器。
4)DHCP服务器收到中继代理发送的请求分组后,知道该报文来自中继代理(因为在请求报文中有一个字段“网关IP地址”定义了中继代理的IP地址),将报文中的跳数字段加1,将应答报文分组发送给DHCP服务器;
5)中继代理收到了DHCP服务器发送的应答报文后,再以单播(常用)或广播的方式发回给DHCP客户。
Notice:DHCP报文只是UDP数据报的一部分(即数据部分),它还要加上UDP首部、IP首部,以及以太网的MAC帧的首部和尾部(只有帧才有尾部)后,才能在链路上传送。
FAQ1:为什么DHCP客户端不使用临时端口号,而使用熟知端口号68?
如果服务器(可以是中继代理,也可以是DHCP服务器)的应答是通过广播传送的,同时DHCP客户(客户A)又选择未用的临时端口,如果其他的主机中碰巧也使用相同的临时端口的应用进程,该进程可能是别的服务的客户(如DAYTIME客户),则这些广播也能被其他的主机(客户B)进程接收到(因为分组被接收是基于socket,而socket=[IP:端口号],两者一样的套接字),显然这是错误的,因为该进程不应该接收该报文(根本没有发出该请求),所以DHCP不适用临时端口号,而采用熟知端口号68。
FAQ2:如果其他的主机(客户B)也使用熟知端口号68,那么将发生什么?
当客户B也使用端口号68,此时两个socket都是一样的,两个客户都会收到同样的报文。此时就需要第三个表示来区分不同的客户。DHCP使用了另外一个编号,称为事物标志(transaction ID),它由涉及DHCP的每一条连接随机选择。两个主机在同一时间选择了相同的事物标志的可能性相当渺小,当然也可以通过返回的客户的MAC地址加以区分。
FAQ3:能否让DHCP客户也使用DHCP服务器的知名端口号?
如果DHCP客户也使用DHCP服务器的知名端口67作为它的端口,那么网络内所有的DHCP服务器会被唤醒来查看每个广播应答(如果所有的服务器都被唤醒,它们将坚持操作码,如果是一个应答而不是请求,就不做处理)。因此可以让所有的客户使用与服务器知名端口相同的知名端口号67。
DHCP分组
上图中的各个字段定义如下:
操作码:定义请求和应答,请求:0 ,应答:1;
硬件类型:定义物理网络的类型,1表示以太网;
硬件地址长度:用于定义物理地址的长度(B),以太网这个值是6;
跳数:由客户设置,若不采用中断代理,该值为0;否则表示该组经历的最大跳数(通常为3);
事物标识:由客户设置,用于对回答和请求进行匹配。服务器要在回答中返回同样的值;
秒数:定义主服务器的时间范围,当备用服务器在等待时间超过这个时间值后才会响应客户的请求,这也意味着此时主服务器没有启动;
标志:目前只是用了最高位,其余位都应当置0。当最高位为1时,表示强制采用广播应答,而不是单播;
客户IP地址:若客户知道自己的IP,则填入其IP(如中继代理向DHCP服务器发送请求);若客户不知道自己的IP,则填入0.0.0.0;
你的IP地址:由服务器设置,服务器将分配各客户的IP地址填入此字段;
服务器IP地址:由服务器设置,包含服务器的IP地址;
网关IP地址:由代理服务器设置,若采用了中继代理,则填入中断代理的IP地址;
客户MAC地址:由客户在请求时设置;
服务器主机名:由服务器在应答时可选地填入,包含服务器域名的字符串,并以\0结束;如果服务器不想在该在该字段填入数据,则必须全部填0;
引导文件名:由服务器填写,有字符串组成,并以\0结尾,该字符串包含了引导文件全路径名;如果服务器不想在该字段中填入数据,则必须全部填0;
选项:有服务器填写,这64B有双重作用:一是可以携带附加信息(如子网掩码、默认网关、DNS服务器IP地址等),二是可以携带特定厂商信息。如果该选项有信息要携带,则前4个字节固定为99.130.83.99(被称为magic cookie,魔块),表示该选项内包含信息,该区域的其余部分都是一个条目表,条目为(1B的标记tag,1B的长度,可变长度值),可变长度的值包含如子网掩码、默认网关和DNS信息等,最后以tag=255结束。如下图所示:
注意:DHCP协议使用UDP,通常与TFTP协议协同工作,DHCP服务器并没有把客户为了引导计算机而可能需要的所有信息发送过去,而是在回答报文中定义了文件的路径名,客户可通过TFTP报文从该路径找到完整的引导信息。
差错控制
在使用DHCP时需要有差错控制,DHCP使用了UDP,而UDP不提供差错控制。因此,DHCP必须提供差错控制,可以通过下面两种方法实现:
1)DHCP要求UDP使用检验和(因为在UDP中,检验和字段是可选的)
2)DHCP客户使用计时器和重传策略来解决对发出的请求没有收到回答的问题。
IP地址的静态分配与动态分配
DHCP服务器有两个数据库,一个是静态数据库,一个动态数据库。
静态数据库由(MAC地址-->IP地址)组成,在这该数据库中查找数据则等价于BOOTP,所以我们常说DHCP协议与BOOTP协议兼容;
动态数据库包括一个可用的IP地址池,该数据库整数DHCP对BOOTP的加强部分,因为BOOTP没有该数据库。
当DHCP客户想DHCP服务器发送请求时,服务器首先检查它的静态数据库,若静态数据库中存在相应的表项时,则返回给该客户永久的IP地址。若静态数据库中不存在该表项,服务器就从可用IP地址池中选择一个IP地址,并把该临时的IP地址分配给客户,并且给出该客户对该IP地址的租用期,同时将相应的表项加入到动态数据库中。当客户对该IP地址的租用期到期时,客户可以停止使用该IP地址,也可以续租。当然,服务器可以选择同意或者不同意续租,毕竟人家是房东嘛。
DHCP的状态转换
在接收DHCP直接的转换转换时,先看看下图中的DHCP的工作过程。
(1)DHCP服务器被动打开UDP端口67,等待DHCP客户发来的报文;
(2)DHCP客户从UDP端口68广播DHCP发现报文DHCPDISCOVER,它处于INIT状态(初始化状态);
(3)凡收到DHCP请求报文的DHCP服务器都发出DHCP提供报文DHCPOFFER,所以DHCP客户可能收到多个DHCPOFFER报文,此时客户进入SELECTING状态(选择状态);
(4)DHCP客户从收到的几个DHCPOFFER报文中选择其中的一个,这个被选中的DHCP服务器把所将要提供给客户的IP地址锁定(待使用,现在客户还不能使用,只有绑定之后才能使用),使该IP地址不会在提供给其他任何客户。同时客户向该DHCP服务器发送DHCP请求报文DHCPREQUEST,客户进入REQUESTING状态(请求状态);
(5)被选择的DHCP服务器发送确认报文DHCPACK,该报文创建了客户MAC地址和它的IP地址之间的绑定。客户收到DHCPACK报文后进入BOUND状态(绑定状态);
(6)进入BOUND状态后,客户就可以使用该IP地址,直到租用时间时间到期。当到达租用时间的50%时,客户就再发送一个DHCPREQUEST报文请求重置IP地址的租用期。此时,客户进入RENEWING状态(请求更新状态);
(7)若DHCP服务器同意重置该IP地址的租用期,则发回DHCP确认报文DHCPACK,客户便重置计时器(复位),客户再次进入BOUND状态,重新回到步骤(5);
(8)若DHCP服务器不同意该客户端重置请求或者不响应该重置请求,应该分类讨论:
A.若DHCP不同意客户端的重置请求,则发回DHCP否认报文DHCPNACK,这是DHCP客户必须立即停止租用该IP地址;
B.若DHCP不响应客户端的重置请求,则客户继续租用该IP地址,当租用期达到87.5%时,DHCP客户必须重新发送DHCP请求报文DHCPREQUEST,此时客户进入REBINGDING状态(请求重新绑定状态);客户进入请求重新绑定状态后,可能会发生如下几件事:
I.若客户收到服务器发送过来的DHCP否定报文DHCPNACK或者租用期到期时,重新回到INIT状态,初始化状态,重新回到步骤(2);
II.若客户收到服务器发送过来的DHCP确定报文(即同意客户重新绑定)后,回到BOUND状态(绑定状态),并把计时器复位,重新回到步骤(5);
(9)DHCP客户在上述状态(BOUND,RENEWING,REBINDING)中,可随时提前终止服务器提供的租用期,此时只需要向DHCP服务器发送DHCP释放报文DHCPRELEASE即可。
注意:上面的DHCP-(discover,offer,request,ack,nack,release),还有这里未涉及的DHCP-(decline,inform)等状态转换报文并不是一个DHCP报文,而是DHCP报文的一部分,这些状态转换报文存在于DHCP报文的选项部分,也就是说,这些状态转换报文均是通过选项来实现的,上面这些状态转换报文在选项中的格式均为:(标记=53,长度=1,值[1-8]),这些值对应的状态映射关系为:1-discover,2-offer,3-,4-decline,5-ack,6-nack,7-release,8-inform。