How does DHCP work?
Posted 2018-10-09 to Ben Burwell’s blog
DHCP(Dynamic Host Configuration Protocol)是大多数网络的组成部分,从小型家庭网络到服务于数千个设备的校园网络。 我最近意识到我对它的运作方式没有充分的理解。 我知道在加入网络时,DHCP 用于从中央服务器获取IP地址,但不清楚它是如何进行协商。 没有IP地址的机器如何与它甚至都不知道地址的服务器通信?
为了解更多信息,我开始使用 Wireshark 抓包并且将计算机连接到网络来查看发生了什么。 我立即发现 DHCP 是 Bootstrap 协议(也称为 BOOTP )的一部分,它通过 UDP / IP 传输。 DHCP 服务器在端口 67 上读写,而 DHCP 客户端在端口 68 上读写。在客户端获取 IP 地址之前,它使用 0.0.0.0
作为其传输的数据包的源地址,并将其数据包发送到广播地址 255.255.255.255
。
对于这个简单情况,我发现获取IP地址涉及四条消息:发现,提供,请求和 ACK 。 在高级别的客户端广播对地址的请求, DHCP 服务器响应提议,客户端基于其接收的提议发出请求,最后 DHCP 服务器确认该请求。
客户端从 0.0.0.0:68
发送UDP广播包到 255.255.255.255:67
。 这是 BOOTP Discover 消息,其中包含有关从网络的权威 DHCP 服务器请求信息的详细信息。 在我观察到的情况下,要求提供以下信息:
请求DHCP租用时间为90天,还包括我的DHCP客户端标识符(MAC地址)和主机名。
在我观察到的情况下,在发送的第一个发现数据包在 1.125 秒后没有响应时,发送了第二个发现数据包。 由于 UDP 不保证传递,因此基本重放机制将成为处理丢弃数据包的协议的一部分。 虽然 TCP 使用序列号来正确地对数据包进行排序,但 BOOTP 似乎使用了一个有些令人惊讶的度量标准:其数据头包含 “seconds elapsed” 字段,第一个被发现的数据包设置为 0 , 1.125 秒后设置为 1 。
服务器发送包含 DHCP Offer 消息的 192.168.1.1:67
到 192.168.1.2:68
的 UDP 数据包。 我们可以通过以下几种方式判断这是提供给我们的:
在此提供的信息中,我们会收到在 Discover 数据包中提出的一些问题的回复。 在这种情况下,我们的租约时间为3600 秒 (也就是一小时,远低于我们要求的90天)。 我们被要求在30 分钟后更新,在 52 分 30 秒后重新绑定,并给出一个 255.255.255.0
的网络掩码。 我们还被告知路由器/ DNS 服务器的地址 192.168.1.1
并提供域名 home(因此我们机器的“FQDN”将是
)。
现在我们收到了提供信息,我们为此做一个请求。 这主要涉及重复初始请求,再次从 0.0.0.0:68
发送到 255.255.255.255:67
。 此外,该消息包括 “Requested IP” 字段,该字段的IP地址来自上一步的提供信息。
最后,DHCP 服务器确认我们的请求。 这样就完成了 IP 地址获取过程。 服务器重申提供的正确参数,包括重新绑定和续订期,网络掩码等。
一些观察结果表明:看到 UDP 用于此协议而不是 TCP 是有意义的,因为 TCP 是面向连接的,并且在此过程开始时我们不知道服务器的地址(也不是我们自己的地址)。 很容易想到通过创建一个提供具有冲突IP地址的虚假租约的欺诈DHCP服务器,能够在网络上造成严重破坏。
凭借我对 DHCP 功能的基本知识,我想更好地理解我在实验过程中遇到的一些问题。 例如,“重新绑定”和“续约”之间有什么区别? 使用“seconds elapsed”作为一种序列号的原因是什么? 我的下一站找到答案的是 IETF RFC 。
在撰写本文时,DHCP RFC 已经进行了三次迭代,还有一些其他扩展/选项 RFC。 这三个都是由巴克内尔大学的 Ralph Droms 编写的。 前两个(RFC 1531 和 RFC 1541 )于 1993 年 10 月发布,最新版本 RFC 2131 于 1997 年 3 月发布。对于历史背景,我想了解整个版本中发生的变化,因此我运行了 $ diff rfc1531.txt rfc1541.txt(这是我喜欢在本地使用RFC存储库的时间之一。在 RFC 1531 和 RFC 1541 之间似乎没有任何协议更改,只是一些格式和措辞更改。运行差异 RFC 1531 和 RFC 2131 产生了相当大的输出,我并不急于阅读,但方便的是,RFC 2131 的 1.1 节被称为“ RFC 1541 的变更”。1997 年的变化描述如下:
本文档更新了 RFC1541 中出现的 DHCP 协议规范。 添加了新的 DHCP 消息类型 DHCPINFORM ; 有关详细信息,请参见第 3.4,4.3 和 4.4 节。 用于将 DHCP 客户端标识到 DHCP 服务器的分类机制已扩展为包括 4.2 和 4.3 节中定义的“供应商”类。 已删除最短租约时间限制。 最后,由于在 DHCP 互操作性测试中获得的经验,已经进行了许多编辑性修改以澄清文本。
有趣的是,我们习惯在 RFC 2119(必须,必须,不需要等)中定义的术语在文档中有明确定义。 经过仔细检查,RFC 2119 也于 1997 年 3 月发布!
认真考虑让我沉思的问题,我了解到“更新”是指客户试图通过重新关联最初授予它的服务器来续订租约。 如果无法联系服务器,或拒绝续订租约,则客户端进入“重新绑定”状态,在该状态下,客户端尝试联系任何 DHCP 服务器以续订其租约或获取新租约。
我只能在“秒”字段中找到一个实际用途的提及(第15页):
为了帮助确保任何 BOOTP 中继代理将 DHCPREQUEST 消息转发到接收原始 DHCPDISCOVER 消息的同一组 DHCP 服务器, DHCPREQUEST 消息必须在 DHCP 消息头的 ‘secs’ 字段中使用相同的值并发送到相同的 IP 广播地址作为原始 DHCPDISCOVER 消息。
我注意到有很多部分都有例如“ DHCP 服务器只有在具有本地管理权限的情况下才可以扩展客户端的租约”(强调添加)的文字。 但是,如果有人要在网络上放置一个流氓 DHCP 服务器,那个没有“本地管理权限”的人呢? 通过创建一个流氓 DHCP 服务器可能会造成一些破坏,尽管可能并不像看起来那么容易。 由于 DHCP 租约通常持续一段时间(数小时或数天),因此现有客户端可能不会受到新服务器出现的长时间影响。 此外,由于绑定机制,当客户端需要更新其租约时,它直接向服务器发送单播消息,它最初获得租约,而不是立即诉诸广播 DHCPDISCOVER 消息。
由于 DHCP 通常用于连续的物理网段,因此可能无法始终使用防火墙来阻止到服务器端口的流量(67)。 这需要某种第 2 层防火墙,我确信它存在,但似乎没有被广泛部署(或推荐)。 当然可以在第 3 或 第 4 层防火墙上设置规则,以阻止未授权充当 DHCP 服务器的机器上的端口 67 的流量,以防止恶意服务器在其物理段之外产生任何影响。
总结: