首页 / 博客 / 本文

DHCP 从原理到排障:DORA 四步、租约状态机与安全防护

🔌 网络服务📅 2026-08-31⏱ 14 分钟

家里 WiFi 一连就能上网,公司电脑插上网线就有 IP——这背后几乎都是 DHCP 在工作。它「存在感为零、出事就是大事」:一旦 DHCP 服务挂掉,新设备拿不到地址,整个网络瞬间「看起来断了」。本文把 DHCP 拆到报文与状态机层面:DORA 四步只是入场券,租约状态机、Options、中继与安全防护才是工程上真正要懂的部分。

一句话原理。DHCP 是一个跑在 UDP 67(服务端)/68(客户端)上的租约协商协议:客户端广播「我要地址」,服务器从地址池里挑一个,双方以四步握手完成「发放—确认」,之后客户端在租期内反复续租。它是 BOOTP 的扩展,天生为「客户端还没有 IP、只能广播」的场景设计。

一、DORA:四步握手逐帧拆解

步骤报文谁发给谁关键内容
1Discover客户端广播(0.0.0.0:68 → 255.255.255.255:67)客户端 MAC、事务 ID(xid)、请求参数列表
2Offer服务器 → 客户端(通常广播)提议的 IP(yiaddr 字段)、租期、掩码、网关、DNS
3Request客户端再次广播「我选了服务器 A 的 Offer」——广播是为了让落选的 B 释放预留
4ACK服务器 → 客户端正式确认,地址正式进入已分配状态

三个值得抠细节的地方:

为什么 Request 还要广播?因为客户端此时仍没有可用 IP,且网络上可能有多台 DHCP 服务器都发了 Offer。广播 Request(内含 server identifier 指明选中谁)让落选服务器知道回收预留地址——这是多服务器环境下不冲突的关键机制。

事务 ID(xid)用来配对。客户端生成随机 xid 贯穿四步,应答报文的 xid 对不上就丢弃。抓包排障时,用 xid 过滤是定位「一次完整租约」的最快方式:udp.port==67 || udp.port==68 再按 xid 追。

NAK 是 ACK 的反面。客户端带着旧租约迁移到别的网段发起 Request,本地服务器发现该地址不属于自己管理的网段,会回 NAK,客户端随即回到 Discover 重新开始。

二、租约状态机:T1、T2 与续租的三次机会

租约不是「到期作废」,而是一条精心设计的时间线。假设租期 8 天(T):

时间点比例客户端动作
T1(续租点)租期的 50%(第 4 天)单播 Request 给原服务器,请求续租(RENEWING)
T2(重绑定点)租期的 87.5%(第 7 天)原服务器没回应 → 广播 Request,任何服务器都可以接管(REBINDING)
租约到期100%(第 8 天)还没续上 → 立即释放地址,回到 Discover 重新来

这套设计保证了平滑与韧性:正常情况在 T1 无感续租(单播、轻量);服务器短暂故障在 T2 还有广播兜底;只有整个网段都没有 DHCP 服务时,客户端才会真正掉线。所以「DHCP 服务器重启 10 分钟」对存量客户端几乎无影响,受伤的只是新入网设备——这也是生产环境把 DHCP 部署成高可用的底气所在。

三、DHCP Options:真正下发「网络世界说明书」的字段

地址只是门票,Options 才告诉客户端「怎么用这张门票」。高频选项:

Option含义说明
1子网掩码与分配 IP 配套
3默认网关可下发多个,按序尝试
6DNS 服务器就是上一篇文章的主角
15域名后缀配合 DNS 的搜索域
51 / 53 / 54租期 / 报文类型 / 服务器标识协议核心字段
82中继代理信息由 DHCP 中继注入,标记客户端真实接入位置
66 / 67TFTP 服务器 / 启动文件名PXE 网络装机全靠它们

工程视角:需要「按接入位置区分网段」时,Option 82 + 中继是标准解法;无盘工作站/PXE 批量装机则依赖 66/67 的组合。

四、跨网段:DHCP 中继(Relay)

广播包默认不出路由器,而 DHCP 的第一步就是广播。每个网段都放一台 DHCP 服务器显然不现实,标准做法是在网关(通常是三层交换机或路由器)上开启 DHCP 中继:

# 思科风格
interface Vlan10
 ip helper-address 10.0.0.53     # 指向中心 DHCP 服务器

# Linux 侧也可用 dnsmasq 模拟
dhcp-range=tag:vlan10,10.10.10.100,10.10.10.200,255.255.255.0,12h

中继把「VLAN10 的广播 Discover」转成「单播发给 DHCP 服务器」,并在报文里填上 giaddr(网关地址)字段。DHCP 服务器看到 giaddr 就知道该从哪个网段的地址池里分配——一个池对应一个网段,靠 giaddr 区分,这是跨网段 DHCP 的核心逻辑。

五、安全:三种攻击与对应防线

攻击手法防线
伪冒 DHCP 服务器在内网抢先响应 Offer,下发假网关/DNS,中间人窃听全部流量交换机开启 DHCP Snooping:非信任端口只许收 DHCP 请求,Offer 一律丢弃
地址池耗尽伪造大量 MAC 发起 Discover,把合法地址池抽干Snooping + 端口限速 + DHCP 服务器开启 MAC 数量限制
租约信息篡改攻击者仿冒续租,抢占他人地址服务器侧开启客户端唯一标识校验(client-id / option 61)

DHCP Snooping 的价值不止 DHCP 本身:它构建的「MAC↔端口绑定表」(snooping binding table)还是动态 ARP 检测(DAI)和 IP Source Guard 的数据基础,三者组合是二层安全的标准套餐。

六、排障清单:拿到 169.254 先别慌

169.254.x.x(APIPA / link-local 地址)意味着「四次握手压根没完成」,不是拿到了错误地址。按这个顺序排查:

  1. 链路层:网线/交换机口灯亮不亮?ethtool eth0、Windows 看网卡状态
  2. 广播可达吗:同网段其他设备正常吗?都挂 → 查 DHCP 服务器/中继;只有一台挂 → 查这台的物理口与网卡
  3. 抓包定位卡在哪一步:有 Discover 没 Offer → 服务器侧或中继问题;有 Offer 没 Request → 客户端防火墙拦了 UDP 68;有 Request 没 ACK → 地址池耗尽或冲突检测失败(服务器日志会有明确记录)
  4. 客户端主动重来:sudo dhclient -r eth0 && sudo dhclient eth0(Linux)或 ipconfig /release && ipconfig /renew(Windows)
  5. 服务器侧看租约库:/var/lib/dhcp/dhcpd.leases(ISC dhcpd)能直接看到谁占着哪个地址、何时到期
# 服务器侧常见日志
dhcpd: DHCPDISCOVER from 00:0c:29:xx:xx:xx via eth0
dhcpd: DHCPOFFER on 10.0.0.101 to 00:0c:29:xx:xx:xx via eth0
dhcpd: DHCPREQUEST for 10.0.0.101 from 00:0c:29:xx:xx:xx via eth0
dhcpd: DHCPACK on 10.0.0.101 to 00:0c:29:xx:xx:xx via eth0
# 若只有 DISCOVER 没有 OFFER:地址池耗尽 / 没有匹配的 subnet 声明

七、服务端选型一页纸

实现定位适用
dnsmasqDHCP + DNS 一体的小型全家桶家庭、实验室、几十人内网
ISC dhcpd事实标准,资料最多(EOL 后社区 fork)传统企业内网、存量系统
KeaISC 官方接班人,API 驱动、支持高可用新建中大型网络、需要与 IPAM 联动
Windows DHCPAD 域环境原生集成微软系企业
总结。看懂 DHCP 只需抓三条主线:① 没有 IP 的客户端只能广播,所以有 DORA 的「两次广播」设计;② 地址是租的不是给的,T1/T2/到期构成一条平滑的续租时间线;③ 一切「拿不到地址」的问题,最终都能用抓包归位到「卡在哪一步」。排障永远从 xid 对对的报文流开始,而不是上来就重启——重启只是把问题藏进了下一次租约。
#DHCP#网络服务#排障#内网运维
广告