印象最深的一次值班,同事说会议室的终端拿不到地址,我远程上去看了一眼,IP是169.254.x.x。那时候第一反应就是抓包,而不是重启交换机。很多人觉得DHCP是最没悬念的网络服务——登录设备后台,把DHCP开关打开,终端就能自动获取地址了。但真到排查现场你会发现,“为什么这台电脑拿到的是169.254.x.x”这个问题,往往不是重启能解决的。我这个DHCP实验想做的,就是把这层“自动”拆开:看看地址到底是怎么从服务器走到客户端的,中间又有哪些环节会悄悄断掉。对刚入门的网工、做运维的同事,还有想搞懂网络基础的朋友,都建议跟着做一遍,这套验证方法在生产环境里一样能用。
1. 我为什么坚持用手抓包的方式做DHCP实验
1.1 只把DHCP功能打开,不算做过实验
如果你只是把DHCP开关打开,终端也能拿到地址,但你对DHCP的理解还停留在黑盒阶段。我做这个实验最想解决的,是三个问题:地址请求报文到底长什么样;服务器怎么知道该给哪个网段分地址;客户拿到地址之后,还会做什么验证动作。这三个问题在配置界面里一个都看不到,只有抓包能回答。
抓包的意义在于把看不见的广播变成可见的报文流。你能清楚看到请求有没有发出去、应答有没有回来、回来时带了什么参数。当网络出问题时,所有证据都在报文里。这次实验我用的设备很普通:一台带路由功能的入门级网络设备,一台普通二层交换机,一台电脑,一部手机或网络摄像头作为第二终端。抓包工具装在电脑上,接到交换机上用笔记本的网卡镜像抓包。
1.2 抓包前的基础动作:释放、请求、观察
步骤如下:
- 在电脑上打开抓包工具,接口选择连接交换机的网卡,抓包过滤器输入
bootp,因为DHCP的报文类型由BOOTP协议承载,这个过滤器能把所有DHCP报文过滤出来。 - 在电脑命令行里先执行
ipconfig /release,让终端放弃当前已有的IP地址。 - 再执行
ipconfig /renew,发起一次全新的地址请求。 - 观察抓包结果,正常情况下应该能抓到四条报文:Discover、Offer、Request、Ack,合起来就是经典的DORA过程。
每条报文各有关键信息。Discover报文里,源IP是0.0.0.0,目的IP是255.255.255.255,带着Option 53,消息类型等于1,它是在问“谁能给我一个地址”。Offer报文里,服务器会在yiaddr字段填上一个候选IP,注意这个字段在Discover里是空的,只有Offer和Ack才会填,这是判断“服务器是否给了地址”的核心字段。Request报文里,客户端会带上Option 54,也就是它选中的服务器标识,告诉所有能听到广播的DHCP服务器“我选了谁,你们不用再等了”。Ack报文则把租期、网关、DNS等参数完整带过来。
第一轮抓包通常只需要几分钟,但我建议你别急着关。把四条报文的源和目的地址都点开看一遍,留意一个细节:客户端的Request是广播方式发出去的,不是直接发给服务器。原因很微妙,后面会专门讲。抓包工具的具体操作我就不啰嗦了,关键是你要建立“先看报文再下结论”的习惯。
提示:如果你的网络里有多个DHCP服务器,一次Request广播可能会诱发多个Offer回来,这反而能帮你发现问题,先记下,后面有专项实验。
2. 实验拓扑与地址规划:一台百元级设备也能完成的完整验证
2.1 拓扑怎么搭
最简单的DHCP实验只需要一个广播域。拓扑是:终端电脑、手机、摄像头这类设备接在二层交换机上,交换机上联一台带路由功能的设备,这台设备同时开启DHCP服务器功能。不需要接外网,因为DHCP是局域网协议,只要服务器和客户端在同一个广播域里就能跑。不接外网还有个好处,减少外部干扰报文,抓包结果干净很多。
如果需要做跨网段实验,就把拓扑扩展成两层:DHCP服务器在网段A,客户端在网段B,中间设备启用DHCP中继功能。我后面会专门讲中继实验的坑,拓扑图先用文字描述清楚:服务器接在交换机A上,中继设备上下各接一个网段,客户端放在网段B。这样就能验证“不同网段怎么通过中继拿到地址”的问题。
2.2 地址池、租期和排除地址怎么规划
实验地址规划我建议这样设置:
| 项目 | 值 | 说明 |
|---|---|---|
| 网段 | 192.168.56.0/24 | 私有实验地址段 |
| 网关 | 192.168.56.1 | 作为默认网关选项下发给客户端 |
| 地址池 | 192.168.56.100 - 192.168.56.199 | 100个可用地址 |
| 排除范围 | 192.168.56.2 - 192.168.56.99 | 给静态设备和服务预留 |
| 保留范围 | 192.168.56.200 - 192.168.56.254 | 手工绑定设备可用 |
| 租期 | 10分钟 | 为了快速观察续租行为 |
租期是这次实验的关键参数。生产环境里租期往往是24小时甚至更长,你等T1续租要等半天,实验等不起。实验环境把租期压缩到10分钟,能在5分钟看到第一次续租尝试,8分45秒左右看到第二次重绑尝试,这是理解DHCP租约生命周期最直观的方法。
这里要强调一下地址池和排除地址的关系。排除范围是给手工配置静态IP的设备预留的,防止自动分配的地址和手工配置的IP撞车。比如你的网关设备、打印机、门禁控制器,都是固定IP,就应该放在地址池之外。很多人在实验里习惯把整个段都塞进地址池,结果网关自己也从DHCP里拿地址,乱套了。
2.3 在设备端做配置的完整步骤
我这次用的是带路由功能的网络设备,配置步骤是通用的:
- 登录设备管理界面,找到DHCP服务器设置。
- 启用DHCP服务,填写开始地址和结束地址。
- 填写网关地址、DNS服务器地址、租期时间。
- 保存配置,确认服务状态为运行中。
如果设备支持命令行配置,配置逻辑也差不多,核心是“地址池、网关、DNS、租期”四件事。示例配置长这样:
ip pool lab network 192.168.56.0 mask 255.255.255.0 gateway-list 192.168.56.1 dns-list 192.168.56.1 lease day 0 hour 0 minute 10配置完以后,在客户端上执行ipconfig /renew,然后ipconfig /all看结果。正常情况下你能看到IPv4地址、子网掩码、默认网关和DNS服务器都自动填好了。在设备管理界面的“客户端列表”里,也能看到当前地址池里哪些地址被租出去了,租期还剩多久。
3. 租约生命周期比你想的更复杂:续租、重绑、释放与冲突检测
3.1 T1和T2:50%和87.5%的续租节点
DORA只是地址分配的第一步,拿到地址之后租约就进入了生命周期管理。租约不是等到期才续,而是提前续。标准规定有两个时间节点:
| 时间节点 | 客户端动作 | 报文方向 |
|---|---|---|
| 0 | 获得完整租约 | Discover/Offer/Request/Ack |
| T1 = 50%租期 | 单播Request续租 | 发给当初分配地址的服务器 |
| T2 = 87.5%租期 | 广播Request重绑 | 发给任意可达的服务器 |
| 到期 | 重新走完整流程 | 或者停止使用该地址 |
用10分钟租期做实验非常清楚。第5分钟抓一次包,你能看到客户端向服务器单播发了一个Request,服务器回一个Ack,租期重新开始计时。如果这个单播Request没有回应,到8分45秒左右,客户端就会改发广播Request,这时候任何能响应它的DHCP服务器都可以接管这个租约。这就是重绑的作用:保证原服务器挂了之后,客户端还能找到新的地址来源。
续租报文比分配报文简单很多,但还是要注意:Request报文里带着Option 54,也就是客户端以为能续租的那个服务器标识。如果广播Request发出去之后,有一台陌生服务器回了Offer,客户端会怎么选?答案是它只认Option 54里标的那台服务器。这个机制在正常网络里问题不大,但在有多台非授权DHCP服务器的环境里,就容易出现客户端迟迟续不上租约的怪现象。
3.2 拿到Offer之后客户端还要做冲突检测
很多人不知道,客户端拿到Offer之后并不会立刻使用这个地址,它要做一次冲突检测。方法是发送ARP探测报文,看看网段里有没有设备已经在用这个IP。如果有人应答,客户端会判定地址冲突,发送DHCPDECLINE报文拒绝这个Offer,然后回到起点重新走Discover流程。
你可以专门做一个实验来复现这个场景。先把终端B手动配置成192.168.56.150,这个地址正好在地址池里。然后让终端A通过DHCP去请求地址。正常情况下DHCP服务器根本不知道终端B占用了这个IP,它会照样把.150分配给终端A。终端A收到Offer后发出免费ARP探测,发现终端B回应了,于是发送DECLINE,整个获取流程重新开始。抓包时你能清楚看到一条DECLINE报文,这在生产环境里就是“IP冲突”报错来源。
这个实验告诉我们:DHCP服务器自己并不保证地址池里的地址绝对空闲,它只能保证“我分配的记录里这个地址是空闲的”。真正发现冲突要靠客户端的免费ARP探测。所以做地址规划时,静态IP和动态地址池一定要分开,否则冲突检测会频繁触发。
3.3 地址池耗尽与DHCPNAK
地址池没地址的时候,情况分两种。有的服务器会保持沉默,不回任何报文,客户端一直等到超时才肯放弃。有的服务器会明确回一个DHCPNAK,告诉客户端“你的请求被拒绝了”。客户端收到NAK之后,会立刻回到初始状态,重新尝试获取地址,或者最终使用APIPA地址。
用10分钟租期做实验时,你可以把地址池起始地址设置成和结束地址一样,人为制造“只有1个地址”的场景。先让终端A拿到地址,再让终端B去请求,就会发现第二种情况下的NAK报文。这个实验虽然简单,但对理解“为什么拿不到地址”很有帮助。很多现场排查到最后,就是因为地址池满了。
4. 实验中最容易翻车的三个点:跨网段中继、多服务器竞争、选项参数
4.1 跨网段地址获取:DHCP中继实验
最值得动手做的实验是中继,因为这里面的坑最多。先解释原理:DHCP Discover是广播报文,路由器默认不转发广播,所以客户端到了别的网段之后,必须靠一台能收广播的设备把请求转给服务器。这个设备就是中继代理。中继做的事情是:收到客户端的广播报文后,把它封装成单播报文发给DHCP服务器,同时在一个叫giaddr的字段里填上客户端所在网段的中继接口IP。
服务器看到giaddr,就能知道该为哪个网段分配地址。这就是DHCP中继的核心逻辑:服务器自己不看报文从哪个物理接口进来,它只认giaddr字段。实验配置分两步走到:
第一步,在客户端所在网段的三层接口上启用DHCP中继,指向DHCP服务器的IP。第二步,在DHCP服务器上建立和客户端网段对应的地址池作用域。如果只开了中继但没建作用域,服务器的行为通常是“沉默”,因为它在giaddr对应的网段里找不到可用地址。
抓包验证时,去服务器侧抓包,看到的Discovery报文很可能源IP不是客户端,而是中继设备的接口地址。点开报文头部,找到giaddr字段,里面就是客户端所在网段的网关地址。这个字段就是跨网段分配的关键证据。
4.2 同一广播域里两台DHCP服务器会发生什么
这个实验我强烈建议你做一次。在同一网段里,把两台设备的DHCP功能同时开启,分别配置不同的网关和DNS。客户端执行地址释放再重新获取,你会惊讶地发现,客户端拿到的地址“看运气”——它可能来自服务器A,也可能来自服务器B,取决于哪个服务器的Offer先到。
原因是客户端广播Discover之后,所有监听广播的DHCP服务器都会响应,客户端选取最先收到的那个Offer。更微妙的是,客户端在Request里带了Option 54标识自己选了谁,这个广播报文会告诉所有服务器。没被选中的服务器会收到消息并收回自己的Offer,但它之前已经发出过一个Offer,如果客户端后来反悔(比如响应超时),就会有混乱。
这个实验在生产环境里的教训很明显:非授权DHCP服务器会造成地址分配混乱。防御手段通常是交换机上的DHCP Snooping功能,把非信任端口的DHCP服务器应答报文丢弃。这个功能的坑也很常见,后面故障排查案例会专门讲。
4.3 选项参数错了会怎样
DHCP不只是分配IP,它还通过选项下发给客户端各种配置。实验里最容易做错的是三个选项:Option 3默认网关、Option 6 DNS服务器、Option 15域名后缀。
网关填错的症状是:地址和DNS都能拿到,但跨网段通信不通。排查时你用ipconfig /all看静态路由条目没有任何问题,因为问题根本不出在客户端,而是DHCP下发了一个错误的网关。实验里你可以故意把网关写成另一个不存在的地址,客户端照样能拿地址、能Ping通同网段,但出不了网段。DNS填错的症状更隐蔽:内网IP通信都正常,但所有域名解析失败。域名的选项在企业环境会影响主机名后缀搜索,实验环境里一般无所谓。
排查这类问题,靠抓包看Offer或Ack报文的Option列表最干脆。地址池配置错了没有?看报文里Option 3和Option 6的值就知道。这也是为什么我坚持说,配置完DHCP之后要养成抓包看一眼的习惯,配置界面显示“成功”不代表下发的内容正确。
5. 一个完整的故障定位过程:客户机一直显示169.254
5.1 现象与第一轮排查
我在某办公区域遇到过这样一次故障:新增的访客终端一直显示169.254.x.x,显然DHCP没成功。第一轮排查先确认链路:换网口、看交换机端口有没有亮,VLAN有没有配错,结果都正常。此时最忌讳的是重启交换机或者重启DHCP服务,因为根本证据还没收集。
169.254地址意味着客户端进行了完整的DHCP发现流程但没有收到任何有效应答,最终启用了APIPA自动私有地址。这个现象说明问题不在客户端,而在“请求-应答”这条链路的某个环节。排查的顺序应该是:客户端侧抓包,服务器侧抓包,中间链路设备逐一确认。
5.2 抓包发现Discover发出去但Offer没回来
在客户机上抓包,结果很清楚:客户端一直在周期性地发出Discover广播,间隔从1秒、2秒、4秒逐渐拉长,但始终没有收到任何Offer。接着去DHCP服务器侧抓包,却连Discover都没有看到。
这时候基本可以锁定问题在客户端到服务器之间的路径上。DHCP报文是UDP,服务器端监听在67端口,客户端源端口是68。中间可能丢弃报文的环节很多,包括ACL、VLAN隔离、DHCP Snooping、防火墙策略。我的排查习惯是先查交换机的DHCP Snooping状态,这个功能在实验和生产环境里都容易被忽略。
5.3 DHCP Snooping把Offer当攻击报文丢了
查配置时发现,这台办公区域的交换机全局开启了DHCP Snooping功能。这个功能默认情况下所有端口都是不信任的,只有手工配置为信任口的端口才会转发DHCP服务器发出的Offer和Ack报文。问题就出在这:连接DHCP服务器的上联端口没有被设置为信任口,服务器回给客户端的Offer报文在交换机上被当作非法报文直接丢弃了。客户端一直傻等,自然永远等不到地址。
修复方法很直接:把连接DHCP服务器端口的交换机端口配置为信任口。如果网络里还有中继链路,连接中继设备上联接口的端口也要一并配置为信任口。改完配置后,客户端重新执行地址释放和获取,地址立刻拿到,抓包也能恢复正常DORA过程。
注意:DHCP Snooping是好用的安全功能,用来防私接路由器,它的坑不在功能本身,而在不完整的信任口配置。开这个功能之前,先把端口信任关系梳理清楚。
5.4 同样现象不同根因:地址池耗尽案例
排查过另一个现场,现象一模一样,客户端也是169.254,但这次服务器侧能看到Discover报文,日志里明确写着“地址池没有可用地址”。原因是地址池范围设置太小,而在线终端远超预期。处理方式就完全不同:扩大地址池范围,或者手动释放掉部分过期租约。
这两个案例放一起,想说明的就是:不要看到一个169.254就套同一个修复方案。先把两边的抓包结果收集起来,判断请求有没有到服务器、服务器有没有回应、回应有没有被丢弃,再用证据决定怎么修。这套思路比任何命令都值钱。
6. 从实验台到生产环境:我的DHCP配置自查清单
6.1 地址池容量与分配率估算
实验里地址池随便填,生产环境不能拍脑袋。我一般按这个思路估算:基础终端数量,加每人平均持有的设备数,加打印机、摄像头、门禁等固定设备,再加访客临时接入,最后留20%到30%缓冲。
举个例子,某楼层日常办公50人,每人平均2台终端,固定设备有5台打印机、20个摄像头,访客预留30个位置。总需求大约155个地址,按缓冲1.3倍,地址池至少规划200个。如果子网本身就够大,地址池填200个没问题;如果子网只剩100个可用地址,那就要提前扩容或者缩减访客预留。
| 设备类型 | 数量 | 说明 |
|---|---|---|
| 办公终端 | 50人 x 2台 = 100 | 含笔记本和手机 |
| 固定设备 | 25 | 打印机、摄像头等 |
| 访客预留 | 30 | 临时接入 |
| 缓冲 | 约45 | 20%-30%余量 |
| 合计 | 约200 | 地址池建议值 |
6.2 保留地址与静态绑定怎么搭配
打印机、服务器这类希望地址固定的设备,用DHCP保留地址绑定MAC是最省心的方式。但要注意,同一个设备如果有有线和无线两张网卡,就有两个MAC地址,需要在DHCP服务器上分别做保留。手工静态IP和设备从DHCP获取的地址池一定要错开,否则一定会出现IP冲突。我的建议是地址池用子网中间一段,静态设备用子网末尾一段,彻底分开。
6.3 安全性与可维护性
安全方面,DHCP Snooping确实能阻止私接路由器,但前提是信任口的配置要跟上。我在前面案例里已经踩过一次坑,配置这类安全功能时一定要同步更新端口信任清单。可维护性方面,生产环境调整DHCP参数后不会立刻全局生效,客户端要等到续租时间节点才会刷新配置。想分批生效,要么改短租期,要么通知终端手动执行一下地址续租,不然现场会有很多终端用着旧网关旧DNS直到租约到期。
6.4 我个人的几条经验
实验环境里把租期设短到几分钟,方便观察续租和重绑行为;生产环境千万不要缩短租期,否则DHCP服务器和网络会因为频繁续租而产生不必要的负载。出问题先抓包再动手,这是每次故障排查最省时间的路径。配置变更记录一定要留清楚,地址池范围、排除范围、中继配置、信任端口,这四类是生产环境里最常出问题的点,每次改动都记一下,后面排查会轻松很多。
做完中继实验或多服务器竞争实验之后,记得把实验装置和配置恢复原状。我有一次就因为在实验台上留着两台DHCP服务器,第二天整个办公网地址分配乱了半天。DHCP这个协议看着简单,但它的行为状态远比表面复杂,实验里把每条细节验证一遍,生产环境遇到问题时才能不慌。