CAPWAP Discovery / Join
主题:CAPWAP Discovery / Join —— AP 怎么找到 AC 并成功"入网"
难度:小白 / 进阶
协议:CAPWAP(RFC 5416)· UDP 5246 控制通道 / UDP 5247 数据通道
一句话总结:企业级 AP 自己不配置 IP、不认 SSID,上线时要"喊一嗓子问周围有没有 AC"——Discovery 是喊话,Join 是报名,Configuration 是领配置;抓包看这三步,就能立刻判断 AP 为什么连不上控制器。
1. 这个小功能是什么?
1.1 生活比喻:新生报到
把 AC(无线控制器)想象成学校招生办,把 AP 想象成刚毕业的新生:
| 阶段 | 打个比方 | 实际动作 |
|---|---|---|
| Discovery Request | 站在校门口喊:"有人吗?这里是不是大学?" | AP 广播 Discovery,问"有没有 AC 收我" |
| Discovery Response | 招生办回一句:"我是 Acme-AC,收录你了" | AC 回 Response,告诉 AP "我是谁、我支持什么" |
| Join Request | 递上报名表:"我叫 XXX,身份是这些" | AP 报上身份信息 |
| Join Response | 招生办盖章:"收下了,这是你的学号" | AC 回 Response,带 Result Code(成功/失败原因) |
| Configuration Req/Rsp | 发教材、课表、校规 | AC 下发 SSID/VLAN/射频配置,AP 回执 |
所以 "AP 上不了线"这个故障,在抓包里就是一串消息的缺失:喊了没人应 / 应了不报名 / 报名被拒 / 报名成功不下发配置。
1.2 关键前提:AP 自己是没有"身份证"的
家用路由器出厂就写死了管理地址、SSID、密码,插上网线就能用。企业级 AP 一开始什么都没有:没有管理 IP、没有 SSID、没有密码,唯一知道的是"AC 的地址在哪"(DHCP option 43 / 静态配置 / DNS / 广播)。
所以 CAPWAP Discovery 的本质是:让一台什么都不知道的设备,在网络里找到它的管理服务器。
1.3 两种部署:集中转发 vs 本地转发(抓包位置完全取决于它)
| 架构 | 数据路径 | 抓包该在哪抓 |
|---|---|---|
| 集中转发(AC 统一转发) | 客户端 → 空口 → AP → CAPWAP 隧道 → AC → 网关 | ① 看 CAPWAP 握手 → 在 AC 上抓 UDP 5246 ② 看用户真实数据(明文 802.11) → 必须在 AP 的 radio 口抓 |
| 本地转发(FlexConnect / 自治 AP) | 客户端 → 空口 → AP → 直接上网 | 在 AP 上抓即可,CAPWAP 只跑控制消息 |
⚠️ 新手最常踩的坑:在 AC 上抓到的是 CAPWAP + DTLS 密文,Wireshark 只能看到"这里有一坨加密数据",看不到 SSID、四次握手、Deauth 原因码。要看无线明文,必须去 AP 侧 radio 口(monitor 模式)。
2. 为什么重要?常见场景
2.1 典型故障场景(运维日常)
- AP 刚上电,指示灯一直闪,就是不上线 → 抓 CAPWAP:Discovery Request 发出去了吗?有 Response 吗?
常见根因:AC 地址写错、DHCP option 43 没下发、AP↔AC 之间 UDP 5246 被 ACL 拦了。 - AP 上线了但没有 SSID / radio 关不掉 → 抓 Configuration 阶段:AC 有下发配置吗?AP 有回执吗?
- AP 反复上下线(flapping) → 抓 Join Response 的 Result Code,看是不是被 AC 主动踢(会话冲突 / 资源不足)。
- 多台 AP 接入后 AC 看不到某台 → 抓 Join Request,看 Radio ID / WTP Name 是不是重复(MAC 配错、克隆机)。
2.2 安全场景
- 伪造 Discovery Response(伪 AC / Evil AP):攻击者抢先应答 Discovery,把 AP 骗到自己手里,再配合 rogue AP 做中间人——这是企业无线里真实存在的攻击路径。同一时段出现多个不同 AC Name 的 Discovery Response 就是红旗。
- 伪造 Configuration 下发:劫持控制通道可以给 AP 下发恶意配置(改 SSID、装 rogue SSID)。
- 控制通道默认明文:UDP 5246 是明文(除非启用 DTLS),能进管理 VLAN 的人都能看到 AP/AC 身份,甚至明文注入报文——这是"管理 VLAN 必须隔离"的根本原因。
3. Wireshark 抓包位置
3.1 抓哪个接口
| 你想看什么 | 抓包位置 |
|---|---|
| CAPWAP 握手(Discovery/Join/Config) | AC 上与 AP 之间的接口;或 AP 的管理口/上联口(不是 radio 口) |
| 无线明文帧(Beacon/认证/四次握手/Data) | AP 的 radio 口(monitor 模式);集中转发时必须去 AP 侧 |
| 用户上网数据(IP 层) | 交换机做端口镜像,抓 AC 下行口或网关口 |
3.2 抓包方向
握手全在 UDP 5246;用户数据全在 UDP 5247(且默认 DTLS/SRTP 加密)。
💡 小技巧:直接用 udp.port == 5246 抓握手最省事;不要一上来就 udp.port == 5247,数据通道流量巨大且默认看不明白。
3.3 前置条件
- AP 到 AC 的管理网络可达(DHCP 能拿到 option 43,或静态配了 AC 地址)
- 抓包主机能看到未加密的 CAPWAP;或已导入 DTLS 会话密钥(见 4.4)
- 无线抓包需网卡支持 monitor 模式(Windows Npcap 对 802.11 捕获过滤支持有限,建议全量抓 + 显示过滤)
4. 可复制过滤器和命令
4.1 显示过滤器(Wireshark)
# —— 全部 CAPWAP 控制报文 ——
capwap
# —— CAPWAP 控制通道(三步握手都在这里)——
udp.port == 5246
# —— 只看 Discovery(喊话 + 应答)——
capwap.control.header.message_type == 1 || capwap.control.header.message_type == 2
# —— 只看 Join(报名 + 盖章)——
capwap.control.header.message_type == 3 || capwap.control.header.message_type == 4
# —— 只看 Join Response 并显示失败原因(最常用的一条)——
capwap.control.header.message_type == 4 && capwap.control.message_element.result_code > 0
# —— AP 是通过哪种方式找到 AC 的(DHCP / DNS / 静态 / AC 指路)——
capwap.control.message_element.discovery_type
# —— AC 名字:确认应答你的 AC 是哪一台 ——
capwap.control.message_element.ac_name
# —— AP 名字(WTP Name):多台 AP 认错名字时看这里 ——
capwap.control.message_element.wtp_name
# —— AP 请求用的是哪种加密(预共享密钥 / X.509 证书)——
capwap.control.message_element.ac_descriptor.security.s == 1 ||
capwap.control.message_element.ac_descriptor.security.x == 1
# —— 数据通道是否启用 DTLS(决定你在 AC 上能不能看到明文)——
capwap.control.message_element.ac_descriptor.dtls_policy.d == 1
# —— 全部配置下发类消息 ——
capwap.control.header.message_type == 5 || capwap.control.header.message_type == 6 ||
capwap.control.header.message_type == 7 || capwap.control.header.message_type == 8
# —— 数据通道保活(CAPWAP-Data 的 keep-alive)——
capwap.keep_alive
# —— 数据通道头部:Radio ID / WBID / 分片标志 ——
capwap.header.rid || capwap.header.wbid || capwap.header.flags.f == 1
📌 注意:capwap.control.message_type 与 capwap.control.header.message_type 是两个不同的字段(前者是消息元素层的,后者是控制头层的)。过滤消息类型请用 capwap.control.header.message_type。
4.2 捕获过滤器(tcpdump / Npcap)
# 只抓 CAPWAP 控制通道(握手)
tcpdump -i eth0 -nn -s0 'udp port 5246'
# 抓握手 + 数据通道
tcpdump -i eth0 -nn -s0 'udp port 5246 or udp port 5247'
# 只抓 Discovery(AP 在喊话),-A 以 ASCII 打印负载
tcpdump -i eth0 -nn -s0 -A 'udp port 5246'
# 抓 AP 所在的整个管理 VLAN 网段(更通用,不依赖端口)
tcpdump -i eth0 -nn -s0 'net 10.10.0.0/24 and udp'
说明:CAPWAP 用 UDP,没有对应的 TCP 端口,所以 tcp port 5246 是错的。
4.3 tshark 命令
# ① 列出本次抓到的所有 CAPWAP 控制消息(消息号 + 序列号 + 长度)
tshark -r capwap.pcapng -Y "capwap.control" \
-T fields -e frame.number -e ip.src -e ip.dst \
-e capwap.control.header.message_type \
-e capwap.control.header.sequence_number \
-e capwap.control.header.message_element_length
# ② 只看 Join Response,看 AC 给的 Result Code(0=成功,非0=失败原因)
tshark -r capwap.pcapng -Y "capwap.control.header.message_type == 4" \
-T fields -e frame.number -e ip.src -e ip.dst \
-e capwap.control.message_element.result_code \
-e capwap.control.message_element.ac_name
# ③ AP 是通过什么方式发现 AC 的
tshark -r capwap.pcapng -Y "capwap.control.message_element.discovery_type" \
-T fields -e frame.number -e ip.src \
-e capwap.control.message_element.discovery_type \
-e capwap.control.message_element.ac_name
# ④ 统计各条消息各出现多少次(看握手是否完整)
tshark -r capwap.pcapng -Y "capwap.control" \
-T fields -e capwap.control.header.message_type | sort | uniq -c
# ⑤ 数据通道:看 Radio ID 有哪些 AP 在用(排查 AP 数量 / ID 冲突)
tshark -r capwap.pcapng -Y "capwap.header.rid" \
-T fields -e frame.number -e ip.src -e ip.dst -e capwap.header.rid | sort -u
# ⑥ 抓包时的实时过滤(等价于显示过滤器)
tshark -i eth0 -Y "udp.port == 5246" -V
参数怎么读
-r capwap.pcapng 读本地抓包文件(-i eth0 才是实时抓网卡)
-Y "过滤器" 显示过滤器,语法和 Wireshark 过滤栏完全一样(注意大写 -Y)
-T fields 按字段输出表格
-e 字段名 要输出哪一列,可写多个 -e 排成多列
-V 打印完整解析树(Verbose),字段多时用
sort | uniq -c 统计每个值出现几次(Windows PowerShell 用 Group-Object)
4.4 想看 DTLS 加密后的 CAPWAP 内容
启用 DTLS 后(capwap.preamble.type == 1 表示后面是 DTLS 头),密文需要会话密钥才能解开:
# 如果设备能导出 SSLKEYLOGFILE,用 tshark 加载
tshark -r capwap.pcapng -o tls.keylog_file:/path/to/sslkeys.log -Y "capwap" -V
说明:-o tls.keylog_file:<路径> 是 Wireshark 3.x/4.x 的 TLS 密钥日志文件偏好项(菜单:Protocols → TLS → (Pre)-Master-Secret log filename)。很多企业设备并不提供这个文件,那就只能在 AP radio 口抓明文,或用厂商自带的调试手段。
5. 关键字段含义
| 字段 | 含义 | 小白解释 |
|---|---|---|
capwap.preamble.version | CAPWAP 版本号(当前为 1) | "这封 CAPWAP 信的格式版本" |
capwap.preamble.type | 0 = 明文 CAPWAP 头;1 = CAPWAP DTLS 头(后面是密文) | "0 = 没加密能直接看;1 = 已加密看不到内容" |
capwap.header.length | CAPWAP 头长度(字节) | "信头有多长" |
capwap.header.rid | Radio ID:哪个 AP(radio)的编号 | "AP 的工号" |
capwap.header.wbid | 绑定标识,1 = IEEE 802.11 | "里面装的是什么协议" |
capwap.header.flags.f | Fragment(是否分片) | "大包被切开传输" |
capwap.header.flags.l | Last Fragment | "这是最后一片" |
capwap.header.flags.k | Keep-Alive 标志 | "保活小包" |
capwap.control.header.message_type | 消息类型:1=Discovery Request,2=Discovery Response,3=Join Request,4=Join Response,5/6=Configuration Status,7/8=Configuration Update,9/10=WTP Event,11/12=Change State,13/14=Echo | "这一句话说的是什么事" |
capwap.control.header.sequence_number | 消息序号(1 字节,0–255) | "第几条消息" |
capwap.control.message_element.discovery_type | 发现方式:0=Unknown,1=静态配置,2=DHCP,3=DNS,4=AC Referral | "AP 是怎么知道 AC 地址的" |
capwap.control.message_element.ac_name | AC 名字 | "控制器的名字" |
capwap.control.message_element.wtp_name | WTP Name(AP 型号+MAC 之类) | "AP 的名字" |
capwap.control.message_element.ac_timestamp | AC 时间戳(NTP 格式) | "控制器的时间" |
...ac_descriptor.security.s | AC 支持预共享密钥认证 | "可以用密码对接" |
...ac_descriptor.security.x | AC 支持 X.509 证书认证 | "可以用证书对接" |
...ac_descriptor.dtls_policy.d | AC 支持 DTLS 加密数据通道 | "数据通道可以加密" |
...ac_descriptor.dtls_policy.c | AC 支持明文数据通道 | "数据通道可以不加密(不安全)" |
capwap.control.message_element.result_code | 结果码:0=成功;1=失败(缺 AC List);2=成功(检测到 NAT);3=Join 失败(未指明);4=资源耗尽;5=未知源;6=数据错误;7=Session ID 已占用;8=硬件不支持;9=绑定不支持;12=配置失败(服务仍提供);13=配置失败(服务未提供);20=缺少必需消息元素 | 排障时最该看的一个字段 |
...capwap_control_ipv4 | AC 的控制面 IPv4 地址 | "控制器自己的管理 IP" |
...capwap_control_wtp_count | 当前已接入的 WTP(AP)数量 | "控制器上现在挂了几台 AP" |
...capwap_timers_discovery | Discovery 重传定时(秒) | "喊几次没人应就放弃" |
...capwap_timers_echo_request | Echo 请求定时(秒) | "多久 ping 一次控制器" |
...ieee80211_ie.radio_id | 该配置属于哪个 radio | "这条配置发给哪台 AP" |
...radio_op_state.radio_state | radio 运行状态 | "AP 的射频开关状态" |
...radio_op_state.radio_cause | 状态变化原因 | "为什么变了" |
capwap.keep_alive | CAPWAP 保活包 | "心跳包,证明隧道还活着" |
capwap.keep_alive.length | 保活包长度(应为 1) | "心跳包体" |
6. 正常表现 vs 异常表现
6.1 正常上线(应该看到这一串)
No.1 10.10.0.50 → 10.10.0.1 UDP 5246 CAPWAP Discovery Request
No.2 10.10.0.1 → 10.10.0.50 UDP 5246 CAPWAP Discovery Response
discovery_type = 2 (DHCP)
ac_name = "Acme-AC"
No.3 10.10.0.50 → 10.10.0.1 UDP 5246 CAPWAP Join Request
wtp_name = "AP-CCF2-0011"
No.4 10.10.0.1 → 10.10.0.50 UDP 5246 CAPWAP Join Response
result_code = 0 (Success)
No.5 10.10.0.1 → 10.10.0.50 UDP 5246 CAPWAP Configuration Request
No.6 10.10.0.50 → 10.10.0.1 UDP 5246 CAPWAP Configuration Status Response
No.7 10.10.0.50 ↔ 10.10.0.1 UDP 5247 CAPWAP-Data(DTLS 隧道建立,之后全是用户数据)
6.2 异常表现对照表
| 现象 | 抓包里的样子 | 大概率原因 |
|---|---|---|
| 抓不到任何 CAPWAP | 完全没有 5246 报文 | AP 没拿到 AC 地址(DHCP option 43 没配);管理口没插好;抓包接口选错 |
| 只有 Discovery Request | 反复出现 message_type=1 | AC 地址不可达;UDP 5246 被 ACL/防火墙拦了;管理 VLAN 不通 |
| Response 来了但 Join 不来 | message_type=2 之后断了 | AC Name / 认证方式 / 加密策略不匹配;AP 侧策略拒绝 |
| Join Response 里 result_code ≠ 0 | = 4 | 资源耗尽(AC 上 AP 数量超 license) |
= 5 | 未知源:AC 上没这个 AP 的记录,或时钟/证书不对 | |
= 6 | 数据错误:AC 与 AP 能力集不兼容(常见于固件升级后) | |
= 7 | Session ID 冲突:同一台 AP 被当成两台上线(MAC 冲突 / 克隆机 / 双重 NAT) | |
| 配置下发失败 | result_code = 12/13 | 12=配置没完全生效但服务在;13=没生效且服务不可用(重点看) |
| 配置下发后 AP 重启 | Change State 消息 + AP 断电重启 | AP 上有"待重启"变更,AC 下发了重启命令 |
| 数据通道没有 5247 | 只有 5246 | UDP 5247 被拦、NAT 穿越失败(result_code=2 表示检测到 NAT)、DTLS 握手失败 |
| 多个不同 ac_name 的 Response | 多个 IP 回 Discovery | 🚩 疑似伪 AC / 伪造 Discovery Response 攻击,立刻排查 |
| preamble.type = 1 但内容乱码 | DTLS 头后全是密文 | 正常现象,需要会话密钥才能解 |
7. 排障与安全用法
7.1 排障:三步定位法
第一步:有没有?
tshark -r capwap.pcapng -Y "capwap.control.header.message_type == 1"
→ 一条都没有 = 物理层/路由/ACL 问题,跟 CAPWAP 本身无关
第二步:回应了吗?
tshark -r capwap.pcapng -Y "capwap.control.header.message_type == 2"
→ 没有回应 = AC 未监听 / UDP 5246 被拦 / 管理 VLAN 不通
第三步:为什么失败?
tshark -r capwap.pcapng -Y "capwap.control.header.message_type == 4" \
-T fields -e capwap.control.message_element.result_code
→ result_code 直接给出失败原因,别猜
再加两条交叉验证:
① Discovery Response 里的 capwap_control_ipv4 是否就是你要找的 AC?不一致说明 DNS / DHCP option 43 下发了错误的 AC 地址。
② AC 上的 capwap_control_wtp_count 是否在 AP 加入后 +1?不涨说明 Join 没成功。
7.2 安全用法
| 用途 | 怎么做 | 目的 |
|---|---|---|
| 检测伪 AC(Evil AC) | 监控 message_type == 2,统计响应源 IP 与 ac_name 的对应关系,出现陌生 IP/陌生 AC Name 即告警 | 发现攻击者抢先应答 Discovery,把 AP 骗走 |
| 审计 CAPWAP 是否加密 | 检查 ac_descriptor.dtls_policy.d == 1,以及抓包里是否出现 capwap.preamble.type == 1 | 控制通道明文 = 管理 VLAN 里任何人都能看身份、甚至注入报文 |
| 发现 rogue AP | 监控 message_type == 3(Join Request)的源 IP 和 wtp_name,比对资产清单 | 发现偷偷接入的 AP |
| 管理面访问审计 | 统计 Join / Change State / Reset 频率 | 发现有人反复重置 AP 搞破坏 |
| 排查配置漂移 | 对比 Configuration Update 下发的 SSID/VLAN 与资产台账 | 找出被私自改配置的 AP |
| 数据通道加密审计 | 检查 capwap.header.flags.k 与 capwap.preamble.type | 确认是否被降级为明文 |
7.3 部署要点(无线网桥 / AP 场景)
- 集中转发(AC 统一转发):AC 上只能看到 CAPWAP + DTLS 密文;要抓无线明文必须去 AP 的 radio 口。前面每一期卡片里"AC 上抓不到 SSID / 四次握手 / BTM 明文"的原因就是这一条。
- 本地转发(FlexConnect):CAPWAP 只承载控制消息,用户数据不经过 AC;AP 侧仍然完整。
- 无线网桥(WDS/桥接):CAPWAP 通常不参与(纯二层透传),所以 CAPWAP 抓不到东西是正常的 —— 别把它当故障。
- 管理 VLAN 隔离是第一原则:控制通道默认明文,AP↔AC 之间必须走独立管理 VLAN 并做 ACL,只放行 UDP 5246/5247。
- 注意时钟:Result Code = 5(未知源)常和 AP 时钟严重偏差导致认证校验失败有关,排障时顺手对一下时间。
8. 合规与隐私提醒
⚠️ 只抓取你拥有或已获得书面授权的网络。
- CAPWAP 控制通道默认明文:抓包文件会直接暴露 AC 名字、AC 管理 IP、AP 名字、AP 标识,等于把整个无线网络的管理面清单公开。抓包文件请按"敏感资产清单"保管。
- Discovery/Join 报文带设备身份:MAC、WTP Name、Radio ID 都可关联到具体设备,不要上传到公开抓包分享站点。
- 不要在生产网做无过滤的全量抓包:CAPWAP + 用户数据混抓很容易把无关用户的上网内容一起带走,尽量用
udp port 5246精确过滤。 - 抓包文件里的 MAC 属于个人信息:在很多司法辖区,无线空间中的 MAC + 位置信息可构成可追踪的行为数据。对外分享前先脱敏(Wireshark → File → Export Specified Packets,或用
editcap)。 - 解密后的内容更要小心:一旦导入 DTLS 密钥,你看到的就是完全明文的管理与用户数据,绝不能外传。
- 厂商密钥导出功能慎用:部分 AC/AP 支持导出 TLS 会话密钥用于抓包排障,导出即等同于交出管理面访问能力,须走审批。
- 合规红线:未授权的 AP 接入、伪造 Discovery Response 属于入侵行为;抓包取证要保留原始 pcap、时间戳与抓包位置,作为安全事件证据。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)