☰
DHCP协议与Wireshark抓包实验:报文、地址池与中继排障
2026/10/26 3:37:58 网站建设 项目流程

做网络基础这一路,DHCP 大概是最容易被跳过去的一节。教材上四张报文图一画,看着谁都会,可真到实验里一抓包,各种问题就冒出来了:DISCOVER 的源地址为什么是 0.0.0.0、REQUEST 明明已经知道服务器是谁了为什么还在广播、抓包过滤器写了半天一条报文都没有、客户端最后拿了个 169.254 开头的地址还不知道错在哪。这篇就围绕DHCP 协议和 Wireshark 抓包实验这两件事,把报文结构、地址池配置、抓包过滤、续租老化、中继排障这一整条链路拆开讲清楚。适合正在啃 HCIA 网络基础、需要动手做实验交作业的,也适合平时在机房、办公网里遇到"上不了网但网线是通的"这类问题、想从抓包里一眼看出根因的运维同行。我尽量按自己当年做实验的顺序写,配置命令、过滤器写法、踩过的坑都摆在明面上,能直接抄去复现。

1. 先把 DHCP 想清楚:它到底在替谁擦屁股

1.1 手工配地址在真实网络里会烂成什么样

刚接触网络的时候,觉得静态配 IP 挺有掌控感的:地址我定的,网关我写的,清清楚楚。可一旦终端数量上到几十台,这套手工活就开始出问题。我见过最典型的一类现场,是办公室里二十多台机器全手工配的地址,表格记在一个谁都不更新的共享文档里。新人来了随手挑一个"看着没人用"的地址,撞上了某台打印机的静态地址,两边都开始间歇性抽风,查了半天才发现是地址冲突。另一类问题是换工位,电脑从三楼搬到五楼,网段变了,网关和掩码全得重配,用户在电话里念 IP 地址给你听,你在这头一个字一个字核对。再往后是笔记本、手机、会议室平板这类移动设备,今天连这个网段明天连那个网段,静态配置根本不现实。

DHCP 本质上就是把这三件事自动化了:地址的分配、地址的回收(租约管理)、以及一堆附加网络参数的下发。第三点经常被忽略,很多人以为 DHCP 只发 IP,其实网关、DNS、域名后缀、甚至 NTP 服务器地址、启动文件路径,都能通过 option 字段一起塞下去。你在电脑上看到"自动获得 IP 地址"打个勾就能上网,背后是四条报文一来一回跑完的。理解了它替谁干活,后面的字段和实验才有意义——你不是在背报文名,你是在看一个自动化的地址管理员怎么跟客户谈合同。

1.2 四个核心报文与状态机怎么对上

教科书上把 DHCP 的交互压缩成 DORA 四步,这四个字母对应 Discover、Offer、Request、Ack。听着简单,但真正做题和抓包时,你得知道每条报文的源目地址、端口、以及它为什么非得这么发。下面这张表是我自己做实验时整理的第一版对照表,后面所有抓包分析都基于它:

报文方向源 IP目的 IP源端口 → 目的端口核心作用
DISCOVER客户端 → 广播0.0.0.0255.255.255.25568 → 67我是一台新机器,谁有地址给我
OFFER服务器 → 客户端服务器地址广播或单播67 → 68我这有个地址,你要不要
REQUEST客户端 → 广播0.0.0.0255.255.255.25568 → 67我选你了,把这个地址正式给我
ACK服务器 → 客户端服务器地址广播或单播67 → 68成交,租期从此刻开始

第一次看这张表最容易卡住的两个点,我当初都卡过。第一个是 DISCOVER 的源地址为什么是 0.0.0.0。道理很直白:客户端此刻根本还没有地址,它没法拿一个不存在的源地址去发报文,只能用全零表示"我还没有身份"。第二个是 REQUEST 为什么还要广播。这一点很多资料一句"为了通知其他服务器"就带过去了,实际含义是:如果你的网络里不止一台 DHCP 服务器(比如一台主用一台备用,或者有人私接了一台路由器开着 DHCP),客户端在 SELECTING 阶段可能收到多个 OFFER,它选定其中一个之后,必须用广播的 REQUEST 把这个决定喊出来,其他发过 OFFER 的服务器听到这条广播,就知道自己那份报价作废了,可以把预留的地址收回池子。要是 REQUEST 用单播悄悄发,其他服务器会一直以为你还在考虑,白占着地址不放。

状态机这条线也得捋顺,因为续租和排障全靠它。客户端从 INIT 开始,发出 DISCOVER 进入 SELECTING,收到 OFFER 发 REQUEST 进入 REQUESTING,收到 ACK 进入 BOUND,此时地址可用,租期开始倒计时。到 T1 时刻进入 RENEWING,向原来那台服务器单播续租;如果没回应,到 T2 时刻进入 REBINDING,改为广播向任意服务器求续租;再没人理,租期到点回到 INIT,地址作废,网络断掉。这条链路上每一步的抓包特征都不一样,后面第 4 节会一条条对着看。

1.3 为什么跑在 UDP 上,67 和 68 为什么要分开

这个问题面试里被问过,我当初的回答是"因为简单",后来才想明白真正的理由是时序上的不可能。DHCP 交互发生在一个客户端还没有合法 IP 地址的时刻。TCP 要建立连接得先三次握手,握手报文本身就要有源 IP 和目的 IP,而此刻客户端既不知道自己该用什么地址,也不知道服务器的地址在哪——它只能广播。广播加无地址,TCP 这条路从物理上就走不通,只能用无连接的 UDP。

端口分开设计也有讲究:服务器固定监听UDP 67,客户端固定监听UDP 68。方向一反过来,端口也跟着换,所以你在 Wireshark 里看到 68→67 就知道是客户端发的,67→68 就是服务器回的,一眼分辨方向,不用去看 IP。这个区分在中继场景里更重要,中继设备要识别出这是 DHCP 报文并做特殊处理,靠的就是这两个端口号。另外,同一台机器理论上可以同时跑 DHCP 服务端和客户端(比如一台服务器既给下面发地址,自己也向上级要地址),端口分开才不至于自己跟自己打架。

再补一个容易被忽略的字段:报文头里的 flags 字段有一位叫广播标志位(B 位)。服务器回 OFFER 和 ACK 时,到底是广播还是单播给客户端,取决于两件事:客户端有没有能力在还没配好地址的情况下接收单播(有些老式客户端不行),以及 B 位有没有置 1。如果 B 位置 1,服务器就必须广播回复。实验里如果你看到 ACK 是广播的,别急着怀疑配置错了,先翻到 flags 那一行看看这一位。

2. 拆开报文看结构:抓包时你到底在看哪几行

2.1 固定头部那十几个字段,真正要盯的不到一半

DHCP 报文的长相是"固定头部 + 可变选项"的结构。固定头部有 236 字节,加上 4 字节魔法 cookie,再往后才是选项区。头部字段一大堆,但做实验和排障真正需要盯的其实就那么几个,我在下面这张表里按使用频率排了序:

字段长度抓包时的实际意义
xid4 字节事务 ID,一次完整交互的四条报文共用同一个值,是串起 DORA 的绳子
yiaddr4 字节服务器打算分给你的地址,OFFER 和 ACK 里最关键的一行
chaddr16 字节客户端硬件地址,实际只用前 6 字节,服务器靠它认人
option 531 字节报文类型,1=Discover 2=Offer 3=Request 5=ACK,抓包筛报文全靠它
giaddr4 字节中继代理地址,非中继场景全零,有值就说明中间过了中继
flags2 字节最高位是广播标志,决定服务器回复用广播还是单播
ciaddr4 字节客户端当前已有地址,续租时才有值,首次申请是全零
siaddr4 字节下一个引导服务器地址,普通上网场景基本用不到
hops1 字节经过的中继跳数,每过一台中继加一,可用来判断有没有环路

我建议你在实验的第一遍就把 xid 这一列加到 Wireshark 的自定义列里。四条报文的 xid 完全一样,你按这一列排序,DORA 就整整齐齐排在一起,比靠时间戳找快得多。chaddr 也值得单独看,多客户端同时申请地址时,服务器是靠这个字段区分谁是谁的,抓包里如果出现同一个 chaddr 反复发 DISCOVER,基本可以断定是这个客户端没收到回复,而不是服务器没发。

2.2 魔法 cookie 和选项区:所有门道都藏在这里

固定头部后面跟着 4 个字节的固定值0x63 0x82 0x53 0x63,业内叫魔法 cookie。它的作用很朴素:告诉解析程序"从这里开始是选项区,按 TLV 格式解"。没有这 4 个字节,解析器没法确认后面的数据到底是选项还是头部里 sname、file 这两个预留的大字段的残留内容。Wireshark 里如果看到"Malformed Packet"之类的提示,有时候就是 cookie 之后的数据长度对不上。

选项区是 TLV 结构,Type 一字节、Length 一字节、Value 变长。常见选项我整理成了下面这个表,实验里至少要把前六个认全:

选项号名称出现位置内容说明
53DHCP Message Type所有报文标识这是哪种报文,抓包筛选的第一依据
54Server IdentifierOFFER/ACK/REQUEST服务器自己的地址,REQUEST 里带上它表示"我选的是这台"
50Requested IP AddressREQUEST客户端要的那个地址,必须和 OFFER 里的 yiaddr 一致
51IP Address Lease TimeOFFER/ACK租期长度,单位秒
55Parameter Request ListDISCOVER/REQUEST客户端点名要哪些参数,比如 1 掩码、3 网关、6 DNS
61Client IdentifierDISCOVER/REQUEST客户端唯一标识,多数实现用 MAC 加类型号拼出来
58 / 59Renewal / Rebinding TimeOFFER/ACKT1 和 T2,不填就按租期的 50% 和 87.5% 默认算
3RouterOFFER/ACK默认网关,客户端拿到后写进自己的路由表
6Domain Name ServerOFFER/ACKDNS 服务器地址,可以带多个
12Host NameDISCOVER/REQUEST客户端主机名,服务器日志里能看到是谁来要地址

选项 55 这个点值得单独说一句,因为它解释了一个常见困惑:为什么我在服务器上配了 DNS,客户端却没拿到?有一种原因是客户端在 option 55 里压根没请求 DNS 这一项(某些精简系统会这样),严格的服务器就只发被请求的参数。实验里如果遇到参数下发不全,先翻到 DISCOVER 的 option 55,看看列表里有没有你要的那一项,再看服务器有没有把它塞进 ACK。

2.3 租期、T1、T2 的数学关系,得自己算一遍

租期这个参数看着简单,实际是最容易设错的地方。协议规定的默认逻辑是:T1 = 租期 × 0.5,T2 = 租期 × 0.875。为什么是这两个比例?50% 的用意是留一半时间给续租折腾,正常情况下 T1 一到就单播去续,服务器一般秒回,续上之后计时器重置,整个过程用户完全无感。87.5% 是最后的安全线,此时客户端开始广播找任何一台服务器,哪怕原来那台挂了也能续上。剩下 12.5% 是给"彻底失败"预留的缓冲,客户端在这段时间里还能优雅地放弃地址、给上层应用一点反应时间,而不是到点直接断网。

拿具体数字算一遍更直观。假设地址池租期配成 3 天:

  • 租期 = 3 × 86400 = 259200 秒
  • T1 = 259200 × 0.5 = 129600 秒 = 1.5 天
  • T2 = 259200 × 0.875 = 226800 秒 = 2.625 天,也就是 2 天 15 小时

也就是说,一台机器拿到地址后,第 1.5 天开始尝试续租,第 2 天 15 小时开始广播求救,第 3 天整租期到点。这些值在抓包里对应 option 51、58、59 三个字段,如果服务器没显式下发 58 和 59,Wireshark 的解析里可能显示为默认推算值,你得自己按上面公式验算,别看到 58 缺失就以为出错了。

租期设长设短是个权衡。设太长(比如 30 天),好处是续租报文少、服务器压力小,坏处是地址池周转慢,会议室这种人来人往的场景很快就被"僵尸租约"占满,人走了地址还占着。设太短(比如 5 分钟),地址回收快,但续租报文会把链路和服务器 CPU 拖得够呛,而且一旦服务器抖动一下,全公司同时掉线重连。我一般的经验值是:办公有线网 1 到 3 天,无线访客网络 2 到 8 小时,会议室平板这类更要短一些。

3. 实验环境与地址池:动手前把地基打对

3.1 拓扑和地址规划,先写在纸上再动手

我吃过亏,图省事直接在模拟器里拖设备,边拖边想地址,结果配到一半发现两个网段撞了,删了重来。后来我养成习惯,任何 DHCP 实验先把地址规划写成一张表,再动手敲命令。下面这个规划是我常用的三网段结构,一台设备做核心(既当网关又当 DHCP 服务器),下挂两个接入网段,再加一个跨网段场景用来验证中继:

网段用途网关DNS分配范围排除范围
192.168.10.0/24服务器所在网段 / 主地址池192.168.10.254192.168.10.2.21 - .200.1 - .20 与 .201 - .253
192.168.20.0/24第二个直连网段,验证接口地址池192.168.20.254192.168.10.2.21 - .200.1 - .20
192.168.30.0/24前端接入网段,无本地服务器,验证中继192.168.30.254192.168.10.2.21 - .200.1 - .20

排除范围这一步千万别省。网关地址、服务器自己的地址、网络设备的管理地址、打印机和监控这类必须固定的设备,全都要从分配范围里刨出去。我在一个真实项目里见过地址池配成从 .1 开始分,结果 DHCP 把网关地址分给了某台笔记本,全网断了十几分钟才定位到。这种事故在实验里复现一次,一辈子记得住。DNS 我用的是内网自建服务器的地址,实验里如果没有,随便填一个同网段的保留地址也行,反正抓包只看字段有没有下发,不看它能不能解析。

3.2 服务器侧配置逐行拆解

模拟器里的命令各家写法有差异,但逻辑是共通的:先全局开启服务,再建地址池,最后在接口上调用。下面是全局地址池的典型写法,我逐行标了它在干什么:

dhcp enable # 全局开关,不开后面所有配置都不生效 ip pool POOL_LAN10 # 建一个名为 POOL_LAN10 的全局地址池 network 192.168.10.0 mask 255.255.255.0 # 声明这个池服务于哪个网段 gateway-list 192.168.10.254 # 下发给客户端的默认网关,option 3 dns-list 192.168.10.2 # 下发的 DNS,option 6 lease day 1 hour 0 # 租期 1 天,等于 86400 秒 excluded-ip-address 192.168.10.1 192.168.10.20 # 排除段,不给客户端 static-bind ip-address 192.168.10.50 mac-address 5489-98aa-bb01 # 按 MAC 固定分配 quit interface Vlanif10 # 客户端网关所在的逻辑接口 ip address 192.168.10.254 255.255.255.0 dhcp select global # 关键:告诉接口用全局地址池

这里第一个坑是dhcp enable忘了敲。配置看着全对,客户端就是拿不到,抓包一看 DISCOVER 发出去没有任何回应。第二个坑是dhcp select global没在接口上配,服务器明明有池子,但接口不知道自己该不该应答,结果同样静默。这两个坑的共同特征是"配置完整但零响应",抓到这种情况,先查这两个开关,比查地址池快。

static-bind这一行是给需要固定地址又不方便手工配的设备准备的,比如打印机、监控头。它的好处是地址由 DHCP 统一管理,不会和别人撞,同时每次设备重启还能拿到同一个地址。用 MAC 绑定时注意 MAC 格式,不同厂商对分隔符的要求不一样,有的要5489-98aa-bb01,有的要54:89:98:aa:bb:01,敲错了会直接报语法错误,这个还算好,报错至少你能发现。麻烦的是 MAC 敲对了但绑错了设备,现象是那台设备拿不到地址、池子里又少了一个,得对着服务器上的地址绑定表一个个核。

3.3 全局地址池和接口地址池,选哪个有讲究

两种池子的区别,我一开始以为只是写法不同,后来才明白是适用场景不同。接口地址池的好处是省事,接口配好地址之后,池子的网段、网关直接从接口继承,不用重复写一遍,配置量小、出错点少。代价是它和接口强绑定,接口一删池子就没了,也不方便做集中管理。全局地址池则相反,网段、网关、DNS 全要自己写,配置长一些,但灵活度高,可以在一个地方管多个网段的池子,还能配合中继给远端网段分配地址。

对比项接口地址池全局地址池
配置量少,网段和网关从接口继承多,需显式声明网段和网关
灵活性低,与接口绑定高,可集中管理多网段
适用场景单网段、小型网络、快速实验多网段、需要中继、需要统一管理
中继场景一般不用必须用,靠 giaddr 匹配网段

接口地址池的写法大概是这个样子,注意关键字是dhcp select interface,其余参数以dhcp server开头:

interface Vlanif20 ip address 192.168.20.254 255.255.255.0 dhcp select interface dhcp server dns-list 192.168.10.2 dhcp server lease day 0 hour 8 dhcp server excluded-ip-address 192.168.20.1 192.168.20.20

我个人的习惯是:实验阶段用接口地址池,快,几行就出效果,适合第一遍跑通 DORA;做中继和多网段实验时必须切到全局地址池,否则你会卡在"为什么远端网段的客户端拿不到地址"这个坑里出不来,因为接口池根本不会去匹配 giaddr 带来的网段信息。

4. Wireshark 实操:从过滤器到四条报文逐个对照

4.1 抓包点选错,后面全都白干

这一步是我当年浪费最多时间的地方。抓包点有三个常见选择,各有各的局限,选错了你会以为"协议没工作",其实是"你看的地方不对":

抓包点能看到什么看不到什么适用场景
客户端本机网卡自己收发的报文,最贴近用户体验别人的报文、被交换机丢弃前的报文快速验证客户端有没有发出去、有没有收到回复
交换机镜像口指定端口或整个 VLAN 的所有报文需要配置镜像,初学者容易配错方向多客户端场景、怀疑服务器没回复
模拟器链路右键抓包该链路上双向流量部分模拟器对广播封装有偏差实验环境最方便,配合真实网卡对照

本机抓包有个坑要注意:Windows 上装抓包工具时,默认可能只勾了本机管理流量那类虚拟网卡,真正的物理网卡没勾,结果抓到一堆无关流量。还有一种情况是无线网卡默认不进入混杂模式,收不到别人的广播,但自己的广播能收到,所以如果你只想看客户端自己的 DORA,本机抓完全够用。

混杂模式这个概念也顺便说清楚:正常网卡收到目的 MAC 不是自己的帧就丢了,混杂模式让它全收下来。查别人的报文必须开混杂模式,查自己的不需要。有些模拟器的链路抓包是默认全收的,这一点对初学者比较友好,不需要额外设置。

4.2 过滤器怎么写才不白抓

Wireshark 有两套过滤器,初学者最容易混:抓包前用的 capture filter 和抓包后用的 display filter。前者的语法是 BPF,写错了会直接抓不到任何东西;后者是 Wireshark 自己的语法,写错了输入框会变红。我建议一律先全量抓,抓完再用 display filter 慢慢筛,这样至少不会漏。显示过滤器里这个协议的字段前缀历史原因叫bootp(协议显示名写的是 DHCP),敲的时候看输入框颜色,绿色才是合法表达式,红色就说明写错了。

bootp # 抓所有 DHCP 报文,最常用的入口 udp.port == 67 || udp.port == 68 # 按端口抓,等价且更保险 bootp.option.dhcp == 1 # 只看 DISCOVER bootp.option.dhcp == 2 # 只看 OFFER bootp.option.dhcp == 3 # 只看 REQUEST bootp.option.dhcp == 5 # 只看 ACK bootp.option.dhcp == 6 # 只看 NAK bootp.hw.mac_addr == 54:89:98:aa:bb:01 # 只看某台客户端的报文 bootp.id == 0x3d1a8f22 # 按 xid 锁定一次交互

这里有个特别典型的错误我一定要提:很多人想抓某台机器的 DHCP,写了ip.addr == 192.168.10.100,结果一条都抓不到。原因是 DISCOVER 和 REQUEST 的源 IP 是 0.0.0.0,目的 IP 是 255.255.255.255,这两个地址里都没有 192.168.10.100,报文自然被过滤掉了。正确的做法是按 MAC 过滤,也就是上面那条bootp.hw.mac_addr,或者干脆按 xid 过滤。这个坑我见过太多人踩,包括我自己第一次做实验。

4.3 四条报文的字段对照实录

先看DISCOVER。你在抓包列表里会看到源 0.0.0.0、目的 255.255.255.255,协议列显示 DHCP 或 BOOTP。点开详情,Bootstrap Protocol 这一段里,Transaction ID 记下来,后面三条都是这个值。Flags 里如果广播位是 1,说明这台客户端要求服务器用广播回复。Client MAC address 是客户端的 MAC,这是服务器识别身份的依据。往下展开 DHCP Message Type,值是 Discover (1)。再往下能看到 Parameter Request List,通常列着 Subnet Mask、Router、Domain Name Server、Domain Name 一大串,这就是客户端在跟服务器"点菜"。有些客户端还会带 Host Name 选项,服务器日志里能直接看到这台机器叫什么。

第二条OFFER,方向翻过来了,源是服务器地址、目的是广播或客户端,端口 67→68。这里最关键的是 Your (client) IP address,它就是服务器准备给你的地址,在 Wireshark 里显示在Bootstrap Protocol段里。继续展开选项区,Server Identifier 填的是服务器自己的地址,Lease Time 是租期秒数,Renewal Time 和 Rebinding Time 就是 T1 和 T2。如果服务器配了网关和 DNS,这里能看到 Router 和 Domain Name Server 两个选项,值和你配置的一模一样。实验做到这一步,你应该能对着自己敲的gateway-list和dns-list逐字核对,这是最有成就感的时刻。

第三条REQUEST,源又回到 0.0.0.0,目的还是广播。它的选项区里有两个东西必须看清:Requested IP Address(option 50)应该等于上一条 OFFER 里给你的地址,Server Identifier(option 54)应该等于 OFFER 里那台服务器的地址。这两个字段同时出现,含义就是"我要你刚才给我的那个地址,并且我只认你这一台"。如果网络里有两台服务器,你会看到两次 OFFER,但只有一条 REQUEST,而且 REQUEST 里的 option 54 明确指向其中一台,另一台的 OFFER 就白发了。

第四条ACK,源服务器、目的广播或客户端,端口 67→68。它的字段结构和 OFFER 几乎一模一样,yiaddr 还是那个地址,租期、网关、DNS 再下发一遍。这也是初学者最容易困惑的地方:两条报文长得这么像,到底差在哪?差在语义。OFFER 是"我提议给你这个地址,你还没定";ACK 是"确认,这个地址现在归你用,租期从这一刻开始算"。你在抓包里可以验证这个差别带来的实际效果——OFFER 之后客户端的地址还是空的,ACK 之后才开始用这个地址发包。

把这四条报文按 xid 分组排在一起看一遍,整个 DORA 就立体了。我第一次完整跑通时,特意把四条报文的截图拼在一起,标注了每个字段的来源和去向,那张图后来一直是我复习 DHCP 的提纲。

4.4 续租、释放、拒绝在抓包里长什么样

续租的报文和首次申请不一样,这一点很容易被忽略。到了 T1 时刻,客户端不再发 DISCOVER,而是直接发一条REQUEST,但这条 REQUEST 有几个特征:源 IP 是自己的地址(不是 0.0.0.0),目的 IP 是服务器的单播地址(不是广播),ciaddr 字段填的是自己的地址而不是空。服务器收到后回一条 ACK,新的租期开始。如果你在抓包里看到一条单播的 REQUEST 紧跟一条 ACK,而且没有 DISCOVER 和 OFFER,那就是续租,不是异常。

到 T2 还没续上,客户端改成广播 REQUEST,这时候目的地址变回 255.255.255.255,源 IP 依然是自己的地址。这一步的意思是"原来那台不在了,谁在都行,给我续一下"。如果有另一台服务器应答了 ACK,客户端就换用新的参数继续用。

释放是客户端主动说"我不用了",发一条 RELEASE,option 53 值为 7。正常情况下很少看到,一般出现在客户端正常关机或者手动释放地址时。抓包里看到它,说明有台设备在礼貌退租,服务器会立刻把地址收回池子。如果一台设备频繁发 RELEASE 又发 DISCOVER,可能是它的驱动或者电源管理有问题,在反复上下线。

NAK是服务器拒绝,option 53 值为 6。出现场景主要有三个:客户端请求了一个不在本网段池子里的地址(比如从别的网络带过来的旧地址)、请求的地址已经被绑定给别人了、或者地址池已经耗尽。NAK 之后客户端必须老老实实回到 INIT 重新发 DISCOVER。排障时看到 NAK,别急着改客户端,先看服务器上这个地址的状态。

还有一种报文叫DECLINE,客户端收到 ACK 之后会用免费 ARP 探一下这个地址有没有人用,如果发现有人应了,就发 DECLINE 告诉服务器"这个地址有人占了,换一个"。实验环境里几乎看不到,真实网络里地址冲突时才会冒出来。如果你抓到了 DECLINE,说明网段里存在手工配置的地址和 DHCP 池子重叠,这是个需要立刻处理的配置问题。

5. 中继与排障:跨网段和"拿不到地址"怎么办

5.1 DHCP 中继为什么必须存在,giaddr 怎么用

DHCP 靠广播工作,而广播帧过不了路由器,这是设计上的硬约束。可现实网络是分网段的,服务器不可能每个网段都放一台。DHCP 中继就是来解决这个矛盾的:它部署在客户端所在网段的网关设备上,听到本网段的 DHCP 广播后,把报文转成单播发给远端服务器,同时在 giaddr 字段里填上自己面向客户端那个接口的地址。服务器收到后看一眼 giaddr,就知道"这个请求来自 192.168.30.0/24",然后去匹配那个网段的地址池。

配置上分两头。中继这一侧要在客户端网段的接口上开启中继并指定服务器地址:

interface Vlanif30 ip address 192.168.30.254 255.255.255.0 dhcp select relay dhcp relay server-ip 192.168.10.10

服务器那一侧,除了要有 192.168.30.0/24 的全局地址池,还必须有一条回程路由。原因是为了让服务器能把 OFFER 和 ACK 送回 192.168.30.0/24,而报文的源地址是中继的接口地址,服务器得知道怎么回到那个网段:

ip route-static 192.168.30.0 255.255.255.0 192.168.10.254

中继最常见的翻车点是回程路由漏配。现象很有迷惑性:你在中继设备上抓包,能看到 DISCOVER 转成单播发出去了,服务器那边也抓到了,也回 OFFER 了,但客户端就是收不到。因为服务器的 OFFER 目的地址是 giaddr,没有回程路由它根本发不出去,或者发到了默认网关上被丢掉。这个现象用"服务器没回"来描述是不准确的,它回了,只是回不到。抓包时两个点都要抓,一对就清楚了。

还有一个细节:中继转发时源 MAC 保留客户端的,hops 加一。抓包里看 hops 字段,如果是 0 说明没经过中继,是 1 说明过了一台。链路上如果配了多级中继(不推荐,但确实有人这么干),hops 会累加,超过阈值报文会被丢弃,这也是排查跨网段拿不到地址时的一个检查项。

5.2 常见故障速查表

下面这张表是我这些年攒下来的,按现象归类,遇到问题先对号入座,能省掉大半时间:

现象抓包看点大概率根因处理方向
客户端拿到 169.254.x.x只有 DISCOVER,无任何回复全局服务没开、接口没调用地址池、链路不通查dhcp enable、接口dhcp select、物理链路
有 OFFER 无 ACKREQUEST 的 option 50 与 OFFER 的 yiaddr 不一致有第二台服务器在抢答、客户端缓存了旧地址隔离其他 DHCP 源,客户端释放地址重试
拿到地址但上不了网ACK 里 option 3 网关、option 6 DNS 是否正确网关配错、DNS 配错、掩码与网关网段不匹配对照地址规划表逐项核对
跨网段拿不到中继侧有转发、服务器侧有 OFFER,客户端无 ACK服务器缺回程路由补一条指向中继接口网段的静态路由
间歇性掉线重连抓包里频繁出现 REQUEST 与 ACK 对租期设得太短,或链路抖动导致续租失败放缓租期,检查链路质量
抓到 NAK 反复重试NAK 后紧跟 DISCOVER,循环往复客户端请求的地址不在当前网段池内清客户端旧租约,核对池子网段
地址池明明没用完却分不出OFFER 后无 ACK、服务器日志报冲突排除地址配得太宽,或存在手工静态地址重叠调整排除范围,排查网段内静态设备
有多条 OFFER 但只想要一台多条 OFFER 的 option 54 不同网段内存在未授权的 DHCP 服务找到源设备关掉,或启用端口级防护把非信任口挡掉

表里最后一条值得展开一句。有些接入交换机支持 DHCP 侦听这类功能,它会把非信任端口上来的 DHCP 服务器报文直接丢掉,只允许信任端口(一般就是上联口)的服务器报文通过。这个功能在办公网里很有价值,能挡住私接路由器乱发地址的问题。配置时注意信任口一定要标对,我见过把接入口错标成信任口的,等于没开;也见过上联口忘了标,导致正常服务器的报文也被丢掉,全网都拿不到地址。

5.3 把抓包工具调成 DHCP 专用视图

做了几遍实验之后,我发现默认的抓包视图看 DHCP 太费劲,主要问题是要滚半天才能找到关键字段,而且四个报文的颜色都一样,筛选全靠手点。后来我做了两件事,效率提升非常明显。

第一件是加自定义列。右键报文详情里想看的字段,选"应用为列",我固定加了这么几列:报文类型(option 53)、yiaddr、option 54 服务器标识、option 51 租期。加完之后整个界面一眼看过去,四条报文的类型、分的地址、服务器是谁、租多久,全在列里排着,不用再逐条展开。这一列配置存在当前配置文件里,下次打开还在,等于给自己做了一套 DHCP 专用的仪表盘。

第二件是配着色规则。在视图菜单里找到着色规则,按 option 53 的取值给六种报文配不同底色:DISCOVER 一个浅色、OFFER 一个、REQUEST 一个、ACK 一个绿色、NAK 一个红色、RELEASE 一个灰。配完之后抓包列表里 DORA 的节奏一眼可见,哪一步断了、哪一步重复了,颜色就告诉你答案。这个技巧我在排查"为什么这台机器每五分钟掉一次线"时立了大功——列表里那串红绿交替的画面,直接指向了续租失败。

另外补一个实用做法:把过滤器保存成按钮。常用的bootp.option.dhcp==1、bootp.option.dhcp==5可以做成过滤器栏右侧的按钮,点一下切换,比每次手打快。实验报告里如果要求贴截图,我建议把四条报文各截一张,展开到选项区,标出关键字段,这比贴一张全屏截图有说服力得多。

5.4 几个反复踩过的坑,提前告诉你

坑一:模拟器和真机行为有差异。模拟器里客户端拿到地址的时机可能比真机快得多,因为你点一下"应用"它就把整个 DORA 跑完了。真机上从插网线到拿到地址通常有几十毫秒到几秒的延迟,还可能有探测阶段。如果你拿模拟器的节奏去判断真机"卡住了",会误判。判断标准应该是抓包里有没有完整的 DORA,而不是快慢。

坑二:xid 对不上,说明抓的不是同一件事。有同学把不同客户端、不同时间的报文硬拼在一起分析,越看越乱。正确做法是先按 xid 排序分组,一次完整的交互用同一个 xid。如果发现同一个客户端有多个 xid 交替出现,那说明它在反复重试,问题出在链路或者服务器侧。

坑三:租期设成小时级以下时,注意单位。有的配置写成lease day 0 hour 0 minute 30,看着是半小时,但如果平台对最小租期有限制,可能被悄悄调成默认值。抓包里核对一下 option 51 的实际秒数,比看配置文件可靠。

坑四:客户端的旧租约是个隐形的坑。换过网段之后,客户端可能还揣着上一个网络的地址去发 REQUEST,服务器一看这个地址不在自己池里,直接回 NAK。这时候现象是"能连上但又断开",很多人会怀疑无线路由器有问题。处理办法很简单,客户端上释放一下地址再看抓包,NAK 消失就说明是这个原因。

坑五:别拿 0.0.0.0 当错误。第一次抓包的人看到源地址全零,第一反应往往是"配置错了"。它不是错,是无地址状态的正常表示。同样,广播目的地址 255.255.255.255 也是正常现象,不是广播风暴。判断广播风暴要看的是单位时间内的报文数量和来源 MAC 数量,而不是看到广播帧就慌。

我个人在实际操作里的体会是,DHCP 这个协议的价值不在协议本身有多复杂,而在于它把"地址管理"这件事从人工手工活变成了可观测、可追溯的自动化流程。而抓包工具的意义,是让你能看见这套流程真实跑起来的样子——你看得见 DISCOVER 怎么出去、OFFER 怎么回来、REQUEST 怎么表态、ACK 怎么落定,那些课本上抽象的名词就变成了屏幕上具体的字段。做完这一轮实验,再遇到"能上内网不能上外网""换了工位连不上"这类问题,你的第一反应会是打开抓包而不是打开浏览器搜答案,这个习惯比记住几种报文值钱得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询