OpenWrt 下 IoT 智能插座“局域网可控、公网不可控”的排查记录
背景
我有一台 Wi-Fi 智能插座,连接到 OpenWrt 软路由的 2.4G AP 上:
- 插座 IP:
192.168.100.196 - 插座 MAC:
88:97:46:45:ad:85 - OpenWrt LAN IP:
192.168.100.1 - USB Wi-Fi:MediaTek
0e8d:7961,OpenWrt 驱动为mt7921u - OpenWrt SSID:
OpenWrt
现象很奇怪:
- 手机和插座在同一个局域网时,可以控制插座。
- 手机切到蜂窝网络后,App 仍能看到插座真实状态,但点击开关后插座没有反应。
- 插座连回原来的小米路由器后,局域网控制和蜂窝远程控制都正常。
这说明 App、账号、云端和插座本身大概率不是根因,问题更可能在 OpenWrt AP 到插座的无线链路上。
抓包方法
在 OpenWrt 上安装并使用tcpdump,分别抓any、br-lan、phy0-ap0三个视角:
tcpdump-iany-s0-U-n-w/tmp/iot_any.pcap\'host 192.168.100.196 or port 5685 or port 53 or arp'tcpdump-ibr-lan-s0-U-n-w/tmp/iot_brlan.pcap\'host 192.168.100.196 or port 5685 or port 53 or arp'tcpdump-iphy0-ap0-s0-U-n-w/tmp/iot_wifi.pcap\'host 192.168.100.196 or port 5685 or port 53 or arp'其中phy0-ap0是无线 AP 接口,能帮助判断包是否已经送到无线侧。
云端域名和协议
断电重连时抓到了 DNS:
iomplatform.hicloud.comDNS 返回:
49.4.34.157 121.36.118.212插座会和云端建立 TCP 长连接:
192.168.100.196 -> 121.36.118.212:5685 192.168.100.196 -> 49.4.34.157:5685协议不是 HTTPS,也不像标准 MQTT。它是在5685/TCP上跑的厂商自定义二进制协议。抓包中能看到部分明文字段:
switch sys.heartbeat sys.data真正的业务参数是二进制密文/签名数据,单靠抓包无法直接还原明文开关值。
关键证据
手机切到蜂窝网络后点击开关,云端确实下发了switch指令:
121.36.118.212:5685 -> 192.168.100.196:xxxxx TCP len=189 SWITCH同一条switch包在两个接口都能看到:
br-lan : 看到了 switch phy0-ap0 : 看到了 switch这说明:
- 不是 App 没发命令。
- 不是云端没下发。
- 不是 OpenWrt 没有转发到无线接口。
但插座没有 ACK 这段 TCP 数据,服务端不断重传同一个switch包:
13:01:59 switch 13:02:00 switch retransmit 13:02:02 switch retransmit 13:02:06 switch retransmit 13:02:13 switch retransmit 13:02:27 switch retransmit 13:02:56 switch retransmit与此同时,插座仍然能发heartbeat,所以“状态同步正常、控制失败”的现象就解释得通了:
- 上行方向:插座到云端正常,所以 App 能看到真实状态。
- 下行方向:云端控制包到了 OpenWrt 无线接口,但插座没有确认/处理,所以远程控制失败。
为什么局域网能控制
局域网内 App 会发现插座的本地服务。抓包中能看到插座发往:
238.238.238.238:5683内容包含:
.well-known.core st=homeCenter这很像 CoAP/局域网发现路径。本地控制不一定走云端 TCP 长连接,所以可以绕过远程控制失败的那条路径。
排除过程
1. 不是云端不支持远程
插座连回小米路由器后:
- 局域网控制正常。
- 蜂窝网络远程控制也正常。
所以软件和云端能力本身没问题。
2. 不是 DNS 问题
设备能解析:
iomplatform.hicloud.com并建立5685/TCP云端长连接。
3. 不是 NAT/路由主路径问题
OpenWrt 上能看到已建立连接:
ESTABLISHED src=192.168.100.196 dst=121.36.118.212 dport=5685状态同步也能证明上行和 NAT 基本正常。
4. 指向 Wi-Fi AP 兼容性
OpenWrt 日志中曾出现过mt7921u相关异常:
vendor request failed:-110 timed out waiting for pending tx Failed to get patch semaphore Failed to set beacon parameters并且 AP 实际显示发射功率一直是:
txpower 3.00 dBm这些都说明这只 MT7921U/MT7961 USB Wi-Fi 在 OpenWrt AP 模式下并不算稳。
固件更新后的验证
后来更新了 MT7921U 固件,OpenWrt 日志显示固件时间已变为:
Build Time: 20260224110909a WM Firmware Build Time: 20260224110949为了验证新固件是否修复了问题,重新启用:
htmode='HT20'注意:HT20需要 WMM,不能同时配置wmm='0'。否则容易导致 hostapd 起不来,日志中会出现:
Failed to set beacon parameters Interface initialization failed修正为HT20 + WMM 默认开启 + uapsd=0后,AP 可以正常广播,但蜂窝网络下远程控制仍然失败。
因此,新固件没有彻底修复该问题。
最终解决方案
把 OpenWrt Wi-Fi 固定为兼容模式:
ucisetwireless.radio0.htmode='NOHT'ucisetwireless.default_radio0.wmm='0'ucisetwireless.default_radio0.uapsd='0'uci commit wireless wifi down radio0sleep3wifi up radio0当前永久配置:
wireless.radio0.htmode='NOHT' wireless.default_radio0.wmm='0' wireless.default_radio0.uapsd='0'运行状态:
ssid OpenWrt channel 6 width 20 MHz (no HT) AP-ENABLED改回该配置后,手机切蜂窝网络也能顺畅控制插座。
原理推测
最可能的原因是:
MT7921U/MT7961 在 OpenWrt AP 模式下,与该 IoT 插座在 802.11n/HT/WMM/A-MPDU 聚合或省电机制上存在兼容性问题。在HT20下,云端 TCP 控制包到达 OpenWrt 的无线接口,但插座没有 ACK。切换到NOHT后,AP 退回更保守的 802.11g/no-HT 模式,绕过了 HT 聚合相关路径,远程控制恢复正常。
这不能 100% 证明一定是 A-MPDU 固件 bug,但证据高度吻合。
代价
NOHT会禁用 802.11n,理论速率从 65 Mbps 级别降到 54 Mbps 或更低。
但对 IoT 插座没有实际影响:
- 插座流量很小。
- 控制包和心跳只有几十到几百字节。
- 稳定性比速率重要。
如果这个 AP 还要给手机、电脑上网,NOHT就不适合作为主力 Wi-Fi。
建议
如果只是给 IoT 设备用:
保留 NOHT + wmm=0 + uapsd=0如果要长期稳定做主力 AP:
- 不建议继续用这只 MT7921U/MT7961 USB Wi-Fi。
- 可以继续让小米路由器或独立 AP 承担 Wi-Fi。
- OpenWrt 只做有线路由、旁路网关或抓包分析。
- 如果必须用 USB Wi-Fi,优先考虑 OpenWrt 社区里 AP 模式更成熟的芯片,例如 MT7612U。
最终结论
这不是插座软件不支持远程控制,也不是云端没有下发命令。
真正的问题在于:
OpenWrt + MT7921U USB Wi-Fi AP 在 802.11n/HT 模式下,对该 IoT 插座的无线下行 TCP 控制包存在兼容性问题。解决方式是禁用 HT/802.11n,使用:
NOHT + wmm=0 + uapsd=0这是一个绕过方案,不是从根上修复 MT7921U 的 AP 兼容性问题。