Linux Wi-Fi实战指南:88x2bu Wi-Fi 热点实战调试

热点开启了,SSID 可见,密码也没输错------但手机就是连不上,不是网络拒绝接入就是一直转圈或者脸上了热点但是上不了网。这篇文章从零开始教你用 tcpdump 抓包定位问题在哪一层的哪一步断的,配合完整诊断脚本和一键修复工具,把「盲猜」变成「实锤」。


1. 问题场景速查

在开始抓包之前,先确认你属于哪一类:

场景 现象 最可能的断点 优先级
场景0 手机上完全搜不到热点 SSID 驱动 AP 模式、信道不兼容、国家码 🔴 最高
场景A 手机能搜到热点,点连接时不弹密码框直接提示「无法连接此网络」 L2 关联(Association)被拒绝 🔴 最高
场景B 手机搜得到热点,输密码后一直「正在获取 IP 地址...」 DHCP 四步交互被阻断 🔴 最高
场景C 手机搜得到热点,输密码后提示「密码错误」或「无法加入」 WPA2 四次握手失败 🟠 高
场景D 密码通过、IP 拿到,但手机显示「已连接,无法访问互联网」 DNS 不可达或 Captive Portal 检测失败 🟡 中
场景E 连接成功但 30 秒~几分钟后自动断开 电源管理 / PSM 帧处理异常 🟢 偏低

接下来的抓包指南将覆盖以上所有场景。
#mermaid-svg-J3Zy8PREwK7RZYgv{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-J3Zy8PREwK7RZYgv .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-J3Zy8PREwK7RZYgv .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-J3Zy8PREwK7RZYgv .error-icon{fill:#552222;}#mermaid-svg-J3Zy8PREwK7RZYgv .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-J3Zy8PREwK7RZYgv .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-J3Zy8PREwK7RZYgv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-J3Zy8PREwK7RZYgv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-J3Zy8PREwK7RZYgv .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-J3Zy8PREwK7RZYgv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-J3Zy8PREwK7RZYgv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-J3Zy8PREwK7RZYgv .marker{fill:#333333;stroke:#333333;}#mermaid-svg-J3Zy8PREwK7RZYgv .marker.cross{stroke:#333333;}#mermaid-svg-J3Zy8PREwK7RZYgv svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-J3Zy8PREwK7RZYgv p{margin:0;}#mermaid-svg-J3Zy8PREwK7RZYgv .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-J3Zy8PREwK7RZYgv .cluster-label text{fill:#333;}#mermaid-svg-J3Zy8PREwK7RZYgv .cluster-label span{color:#333;}#mermaid-svg-J3Zy8PREwK7RZYgv .cluster-label span p{background-color:transparent;}#mermaid-svg-J3Zy8PREwK7RZYgv .label text,#mermaid-svg-J3Zy8PREwK7RZYgv span{fill:#333;color:#333;}#mermaid-svg-J3Zy8PREwK7RZYgv .node rect,#mermaid-svg-J3Zy8PREwK7RZYgv .node circle,#mermaid-svg-J3Zy8PREwK7RZYgv .node ellipse,#mermaid-svg-J3Zy8PREwK7RZYgv .node polygon,#mermaid-svg-J3Zy8PREwK7RZYgv .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-J3Zy8PREwK7RZYgv .rough-node .label text,#mermaid-svg-J3Zy8PREwK7RZYgv .node .label text,#mermaid-svg-J3Zy8PREwK7RZYgv .image-shape .label,#mermaid-svg-J3Zy8PREwK7RZYgv .icon-shape .label{text-anchor:middle;}#mermaid-svg-J3Zy8PREwK7RZYgv .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-J3Zy8PREwK7RZYgv .rough-node .label,#mermaid-svg-J3Zy8PREwK7RZYgv .node .label,#mermaid-svg-J3Zy8PREwK7RZYgv .image-shape .label,#mermaid-svg-J3Zy8PREwK7RZYgv .icon-shape .label{text-align:center;}#mermaid-svg-J3Zy8PREwK7RZYgv .node.clickable{cursor:pointer;}#mermaid-svg-J3Zy8PREwK7RZYgv .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-J3Zy8PREwK7RZYgv .arrowheadPath{fill:#333333;}#mermaid-svg-J3Zy8PREwK7RZYgv .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-J3Zy8PREwK7RZYgv .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-J3Zy8PREwK7RZYgv .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-J3Zy8PREwK7RZYgv .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-J3Zy8PREwK7RZYgv .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-J3Zy8PREwK7RZYgv .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-J3Zy8PREwK7RZYgv .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-J3Zy8PREwK7RZYgv .cluster text{fill:#333;}#mermaid-svg-J3Zy8PREwK7RZYgv .cluster span{color:#333;}#mermaid-svg-J3Zy8PREwK7RZYgv div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-J3Zy8PREwK7RZYgv .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-J3Zy8PREwK7RZYgv rect.text{fill:none;stroke-width:0;}#mermaid-svg-J3Zy8PREwK7RZYgv .icon-shape,#mermaid-svg-J3Zy8PREwK7RZYgv .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-J3Zy8PREwK7RZYgv .icon-shape p,#mermaid-svg-J3Zy8PREwK7RZYgv .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-J3Zy8PREwK7RZYgv .icon-shape .label rect,#mermaid-svg-J3Zy8PREwK7RZYgv .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-J3Zy8PREwK7RZYgv .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-J3Zy8PREwK7RZYgv .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-J3Zy8PREwK7RZYgv :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ❌ 搜不到
✅ 能看到
不弹密码框

直接提示无法连接
弹出密码框

输入密码后
一直转圈

获取IP中
密码错误

无法加入
连上了
❌ 已连接

无互联网
✅ 能上网
过一会就断
不知道卡在哪

先全抓再分析
📱 手机连不上热点
能看到

热点SSID吗?
👉 场景0: 第4节

驱动/信道/国家码排查
点连接后

什么反应?
👉 场景A: 第5节

抓关联帧分析原因码
输密码后

提示什么?
👉 场景B: 第6节

抓DHCP四步交互
👉 场景C: 第7节

抓WPA四次握手
能上网吗?
👉 场景D: 第8节

DNS/路由二分法
会断连吗?
👉 场景E: 第9节

抓管理帧看原因码
👉 第3节

tcpdump 全阶段抓包

一把梭写入 pcap


2. 准备工作

2.1 确认无线接口名称

bash 复制代码
ip link show | grep -E "^[0-9]+:" | grep -v lo

记住输出中类似 wlan0wlx... 的接口名,后面的所有命令中将用 wlan0 代替,你需要替换为自己的实际接口名。

2.2 安装必要工具

bash 复制代码
sudo apt update
sudo apt install -y tcpdump iw wireless-tools net-tools

3. tcpdump 全阶段抓包:一站式捕获 wlan0 所有数据包

前面各场景的抓包命令都是分阶段的------抓 DHCP 只开 67/68 端口、抓 WPA 只开 EAPOL 帧。但实际调试时,你往往不知道问题出在哪一步。这时最有效的做法是:一把梭抓下所有包,事后拿着 pcap 文件慢慢翻。

3.1 核心命令:捕获所有接口所有流量

bash 复制代码
# 最基本:抓 wlan0 上所有包,实时打印到终端
sudo tcpdump -i wlan0 -v -e -n

但这三个参数各有取舍,先把选项说清楚:

参数 作用 什么时候用 什么时候不用
-v / -vv / -vvv 详细程度逐级递增 调试阶段,需要看帧内字段 高流量场景(打印太多会丢包)
-e 打印 MAC 地址 Wi-Fi 调试必加------没有 MAC 你分不出谁发的包 永远加,不差这一点
-n 不解析 DNS(IP 直接显示) 调试阶段,快了十几倍 需要看域名时去掉
-X 十六进制 + ASCII 打印每个包 需要在帧体内翻字段时(如找 status code) 输出爆炸,只在确认阶段用
-x 仅十六进制(比 -X 少 ASCII 那半) 同上但更紧凑 同上
-c N 抓 N 个包后自动停 只想看前几次交互 要等很久才能复现时不要限

接下来我会挨个列出我在Ubuntu上使用rtl88x2bu Wi-Fi模块遇到的问题

4. Issue Case: 连接热点时提示"网络拒绝接入,连接失败"

测试步骤:

  1. 在Ubuntu上开启AP
  2. 手机连接这个AP
  3. 执行抓包命令
bash 复制代码
sudo tcpdump -i wlan0 -v -e -n

4.1 问题2:tcpdump抓不到任何包

4.1.1 Log 摘要:

tcpdump抓不到任何包

4.1.2 Log 分析:

在执行手机连接AP时,tcpdump是不可能抓不到包的。

首先排查驱动,发现问题出在 CONFIG_RTW_GRO = y 。 GRO (Generic Receive Offload) 是内核的一种收包聚合机制,它会把多个连续的 TCP 数据包合并成一个大的 "super-packet" 再交给上层协议栈。这会导致 tcpdump 在抓包时看到的是被聚合后的大包,而不是原始的小包,甚至可能完全看不到包。

4.1.3 解决方案

方案一:运行时关闭 GRO(推荐先试)

不需要重编译,接口启动后执行:

bash 复制代码
sudo ethtool -K wlan0 gro off

方案二:编译时禁用 GRO(永久修复)

修改 Makefile :

bash 复制代码
#改前
CONFIG_RTW_GRO = y
#改后
CONFIG_RTW_GRO = n```

然后重新编译安装驱动。

4.2 问题1: NetBIOS 广播泛洪

4.2.1 Log 摘要:

tcpdump: listening on wlan0, link-type EN10MB (Ethernet), snapshot length 262144 bytes

23:53:03.601897 90🇩🇪80:18:48:23 > ff:ff:ff:ff:ff:ff, ethertype IPv4 (0x0800), length 286: (tos 0x0, ttl 64, id 35472, offset 0, flags DF, proto UDP (17), length 272)

192.168.0.1.138 > 192.168.0.255.138: UDP, length 244

23:53:33.637742 90🇩🇪80:18:48:23 > ff:ff:ff:ff:ff:ff, ethertype IPv4 (0x0800), length 92: (tos 0x0, ttl 64, id 65070, offset 0, flags DF, proto UDP (17), length 78)

192.168.0.1.137 > 192.168.0.255.137: UDP, length 50

23:53:35.645799 90🇩🇪80:18:48:23 > ff:ff:ff:ff:ff:ff, ethertype IPv4 (0x0800), length 92: (tos 0x0, ttl 64, id 65416, offset 0, flags DF, proto UDP (17), length 78)

192.168.0.1.137 > 192.168.0.255.137: UDP, length 50

4.2.2 Log 分析:

这不是代码问题,而是网络广播流量问题。抓到的这些都是 NetBIOS 广播包(UDP 137/138 端口),来自 192.168.0.1。

92.168.0.1 就是这个 AP 自己(Ubuntu 虚拟机)的 IP,这些 NetBIOS 广播包是 Ubuntu VM 上的 Samba/nmbd 服务 发出来的,通过 AP 广播到了连接它的手机上。

4.2.3 解决方案:

bash 复制代码
sudo systemctl stop nmbd
sudo systemctl disable nmbd

用不到 Samba 文件共享的话,这些服务完全多余,关掉后广播泛洪就没了,WLAN 也会干净很多。

4.3 问题3: DHCP 服务(dnsmasq)没在 AP 上响应

解决了广播防洪的问题,重新开始抓包。

4.3.1 Log 摘要

01:13:01.459082 b2:14:a4:77:1a:7d > 33:33:00:00:00:02, ethertype IPv6 (0x86dd), length 70: (hlim 255, next-header ICMPv6 (58) payload length: 16) fe80::b014:a4ff:fe77:1a7d > ff02::2: icmp6 sum ok ICMP6, router solicitation, length 16

source link-address option (1), length 8 (1): b2:14:a4:77:1a:7d

01:13:01.558714 b2:14:a4:77:1a:7d > ff:ff:ff:ff:ff:ff, ethertype IPv4 (0x0800), length 344: (tos 0x10, ttl 64, id 0, offset 0, flags DF, proto UDP (17), length 330)

0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from b2:14:a4:77:1a:7d, length 302, xid 0xe1647245, secs 1, Flags none

Client-Ethernet-Address b2:14:a4:77:1a:7d

Vendor-rfc1048 Extensions

Magic Cookie 0x63825363

DHCP-Message (53), length 1: Discover

Client-ID (61), length 7: ether b2:14:a4:77:1a:7d

MSZ (57), length 2: 1500

Vendor-Class (60), length 15: "android-dhcp-13"

Hostname (12), length 11: "rong-yaoX40"

Parameter-Request (55), length 12:

Subnet-Mask (1), Default-Gateway (3), Domain-Name-Server (6), Domain-Name (15)

MTU (26), BR (28), Lease-Time (51), RN (58)

RB (59), Vendor-Option (43), URL (114), Unknown (108)

4.3.2 Log 分析

关键判据 :整段 log 里只有 DISCOVER ,没有 OFFER 。正常流程应该是:

手机: DHCP DISCOVER

AP: DHCP OFFER ← 没出现!

手机: DHCP REQUEST ← 也没出现

AP: DHCP ACK ← 也没出现

所以问题确认就是 DHCP 服务(dnsmasq)没在 AP 上响应 。修法同上:在 Ubuntu VM 上检查是否安装dnsmasq并重启 dnsmasq。

4.3.3 解决方案:

确认dnsmasq是否安装

bash 复制代码
# 检查 dnsmasq 是否在运行(NetworkManager 热点依赖它做 DHCP)
systemctl status dnsmasq
# 如果未安装,执行
sudo apt update && sudo apt install -y dnsmasq
# 手动运行DHCP服务
sudo dnsmasq -d -i bridge0 --dhcp-range=192.168.0.100,192.168.0.200,12h --port=0 --no-resolv --bind-interfaces

手机再次尝试连接这个AP就能连接成功了。

5. 复盘

三个问题有严格顺序依赖:

复制代码
GRO吞包 → 抓不到任何包 → 修GRO → NetBIOS泛洪 → 淹没有用包 → 关nmbd → DHCP无响应 → 只有Discover没Offer → 装dnsmasq → ✓
问题 根因 修复
GRO 吞包 CONFIG_RTW_GRO=y ethtool -K wlan0 gro off
NetBIOS 泛洪 nmbd 后台广播 systemctl disable nmbd
DHCP 无响应 dnsmasq 未安装 apt install dnsmasq && dnsmasq -d -i wlan0 --dhcp-range=... --port=0

关键认知:无包 = 驱动有问题;全噪 = 服务有问题;只有 Discover = DHCP 有问题。Wi-Fi 连接链 L2→WPA→DHCP→DNS,每步都可能断。