DHCP(动态主机配置协议)主要用来给网络里的设备分发 IP 地址,在一个局域网里只要有一个 DHCP Server 服务,所有加入到这个局域网的设备都可以通过它获取一个自己的 IP 地址,从而进行通信。如果没有 DHCP 服务,就需要人工给每一个设备配置上 IP 地址才能正常上网。

为什么需要 DHCP?

  1. 自动化: 避免了手动输入 IP、掩码、网关的繁琐。
  2. 防止冲突: 服务器统一管理,确保同一个 IP 不会被分配给两个设备。
  3. 地址重用: 设备离开网络后,IP 会被收回重新分配,提高地址利用率。

租约 (Lease)

IP 地址并不是永久分给你的,而是有租期的:

  • 续租 (Renewal): 当租期过去 50% 时,客户端会直接向服务器发送请求,尝试延长租期。
  • 过期 (Expiration): 如果租期到了客户端还没续租成功,就必须停止使用该 IP,并重新开始 DORA 过程。

架构

DHCP 服务采用 UDP 协议,它是一个双端协作的架构,服务端和客户端各自使用一个固定的端口。

  • DHCP Server 监听端口:UDP 67(处理客户端发来的请求)。
  • DHCP Client 监听端口:UDP 68(接收服务端发回的响应)。
    DHCPv6 的默认 UDP 端口是:
  • DHCPv6 Client 监听端口:UDP 546
  • DHCPv6 Server/Relay 监听端口:UDP 547

常见的 DHCP Server 软件

    • dnsmasq:轻量级、资源占用极小。完美集成 DHCP 和 DNS 服务,常用于家用路由器(如 OpenWrt)、轻量级服务器和局域网环境。
  • ISC DHCP Server (dhcpd):曾经的行业标准和老牌标杆,功能极其强大稳定。不过 ISC 官方目前已停止维护,老系统上依然很常见。
  • Kea DHCP:ISC 官方开发的下一代 DHCP 服务器,用来替代老旧的 dhcpd。它支持模块化设计、通过 SQL 数据库存储租约、提供高性能的 REST API,适合大型企业或 ISP 环境。
  • Keos (Coreos/CoreDHCP):现代化的、用 Go 语言编写的 DHCPv4/v6 服务器。设计非常灵活,常用于云原生或定制化的网络基础设施。
  • Systemd-networkd:现代 Linux 发行版内置的系统组件,不仅能当客户端,只要在配置中开启 DHCPServer=yes,它自己就能变身为一个轻量级的 DHCP 服务器。

常见的 DHCP Client 软件

  • dhclient:同样由 ISC 开发,是 Linux 生态中最经典、使用最广泛的命令行客户端。
  • dhcpcd:一个非常流行且轻量级的开源 DHCP 客户端,广泛用于 Arch Linux、Raspberry Pi OS(树莓派)等系统。它对 IPv6 的支持和网卡的热插拔处理得非常好。
  • NetworkManager (nmcli):现代主流 Linux 桌面和服务器系统(如 Ubuntu、CentOS/RHEL)默认的网络管理工具。它内部集成了自己的 DHCP 客户端插件(通常基于 dhclient 或内置代码),自动帮你在后台处理连接。
  • Systemd-networkd / systemd-networkd-wait-online:Systemd 生态中的网络配置工具,通过在接口配置文件中设置 DHCP=yes,即可启用它内置的轻量级 DHCP 客户端功能。
  • udhcpc:嵌入式领域的绝对主力。它是 BusyBox 工具箱的一部分,体积微小,广泛运行在各种嵌入式 Linux、百元路由器以及 Docker 容器镜像(如 Alpine Linux)中。
  • 操作系统内置客户端:Windows 的 dhcpcsvc 服务(底层通过 ipconfig /renew 触发)以及 macOS 的网络框架,都各自内置了闭源但标准的 DHCP 客户端。

IPv4 下 DHCP 的工作过程 DORA

DHCP 的工作原理可以简单概括为“四个阶段的握手”,通常被称为 DORA 过程。它的核心目标是让新加入网络的设备自动获取 IP 地址,而不需要手动配置。

1. 发现阶段 (DHCP Discover)

当你的电脑或手机连接到 Wi-Fi 或插上网线时,它并不知道网络中谁是路由器,也不知道自己该用什么 IP。

  • 动作: 客户端发送一个广播包(目标地址为 255.255.255.255)。
  • 含义: “大家好,我是新来的,我的 MAC 地址是 XX:XX,请问这儿有 DHCP 服务器能给我发个 IP 吗?”

2. 提供阶段 (DHCP Offer)

网络中的 DHCP 服务器(通常是你的路由器)收到广播后,会检查自己的地址池。

  • 动作: 服务器预留一个未使用的 IP,并发回一个广播响应(包含拟分配的 IP、子网掩码、租期、网关和 DNS)。
  • 含义: “你好,我在这里。我手里有个 IP 地址 192.168.1.50 还没人用,你要吗?”

3. 请求阶段 (DHCP Request)

客户端可能会收到多个服务器发来的 Offer(在大型网络中常见),它通常会选择第一个收到的。

  • 动作: 客户端再次发送广播,明确告知所有服务器它接受了哪一个 Offer。
  • 含义: “谢谢!我决定使用服务器 A 提供的 192.168.1.50 了,其他的服务器可以把你们预留的地址收回去了。”

4. 确认阶段 (DHCP Acknowledgment / ACK)

服务器收到请求后,正式将该 IP 绑定到客户端的 MAC 地址。

  • 动作: 服务器发送一个 ACK 确认包。
  • 含义: “没问题,这个地址正式租给你用了!记得在租期到期前找我续租。”

IPv6 下 DHCP 工作过程

IPv6 下可以不依赖 DHCP,它实现了一种更高级的自动配置方案。
在 IPv6 下,路由器会定期广播 RA(路由通告,Router Advertisement) 报文,告诉大家:“本网段的前缀是 2001:db8:1::/64”。客户端收到前缀后,自己结合自己的 MAC 地址(通过 EUI-64 算法)或生成一个随机数,拼出后 64 位,自动组合成一个全球唯一的 IPv6 地址。
这个过程称为 SLAAC(无状态地址自动配置)。
但是用了 SLAAC,人们还是发明了 DHCPv6,主要有两个原因,一个是早期的 SLAAC 无法下发 DNS 服务器、NTP 服务器等其他配置信息(现在配合 RDNSS (Recursive DNS Server, RFC 8106) 已经可以下发了)。第二个是 SLACC + RDNSS 方式下,客户端的 IPv6 是会隔一段时间变化的(为了隐私,现代操作系统(iOS、Android、Windows 11)默认开启了“隐私扩展(Privacy Extensions)”,每隔几小时就会随机换一个 IPv6 地址。),这样合规、审计、安全准入就都没法做了。

有状态和无状态

IPv6 下的 DHCP划分了有状态和无状态两种模式。
模式 A:无状态 DHCPv6 (Stateless) —— 最常用

  • 分工: 路由器通过 RA 报文把 IP 地址前缀发给客户端(客户端自己拼出 IP)。
  • DHCPv6 的作用: 客户端通过 DHCPv6 只去向服务器索要 DNS、域名等附加信息。
  • 特点: 这就是为了解决早期 SLAAC 不下发 DNS 等信息设计的。服务器不记录、不管理谁用了什么 IP,非常轻量。

模式 B:有状态 DHCPv6 (Stateful) —— 类似于 IPv4

  • 分工: 路由器的 RA 报文明确告诉客户端:“我这里不给前缀,你必须去找 DHCPv6 服务器要 IP”。
  • DHCPv6 的作用: 服务器统一分配完整的 IPv6 地址,并在数据库中记录 MAC 与 IP 的绑定关系(租约)。

工作过程 SARR

如果开启了有状态 DHCPv6,它的交互流程和 IPv4 极其相似,但报文名称和机制变了(统称为 SARR 过程):

阶段 IPv4 (DORA) IPv6 (SARR) 含义
1. 发现 Discover Solicit (请求) 客户端广播寻找网络中的 DHCPv6 服务器。
2. 提供 Offer Advertise (通告) 服务器回应:“我这里有 IP 和配置可以给你”。
3. 请求 Request Request (请求) 客户端确认选择该服务器的配置。
4. 确认 ACK Reply (答复) 服务器正式确认,租约生效。

模拟测试

有时想要测试下 DHCP 服务端是否正常工作,可以使用 dhclient,但是这个命令执行后会真的请求一个 IP 地址并配置到本机,不太适合测试用。所以可以使用 nmap,它会尝试获取一个 IP 地址并将 DHCP Server 的响应信息打印出来,但是不真的修改本机 IP。

sudo nmap --script broadcast-dhcp-discover -e en0