摘要
给足信任和权限,AI 比想象的还要强。
把小米智能音箱连接到新家的路由器后,进行语音操作时,一直提示 “网络服务遇到问题”,使用 Pi + Deepseek v4.1 flash 进行调查,仅耗时半小时就定位并修复了问题。
背景
最近搬家了,之前部署的 HomeLab 机房还留在老家,由于新家没有太多 IT 设备,所以选择了一台在吃灰的 红米 AX6S 刷成 OpenWRT ,同时为了保持内网的无感直达,在这台 OpenWRT 上部署了 EasyTier 与老家 HomeLab 的进行互联。这一切都非常顺利,EasyTier 一把打通,成功路由回了 HomeLab 里的开发机。
现象
把小米智能音箱重置后接入新家网络,能够连接成功,在米家 APP 上也可以看到和操作音箱,但是通过 “小爱同学” 唤醒后,任何指令都只会报 “网络服务遇到问题,请稍后再试吧”。这就纳了闷了,其他米家设备,全部都是正常的,能够正常通过米家 APP 进行控制,唯独 “小爱同学” 不行。
调查
我先自己着手调查了一圈
- 公网:正常
- DNS 解析:正常
- 防火墙:正常
算了,干脆让 Agent 帮我查吧,把 OpenWRT 的 SSH 配成公钥登录,交给 Agent,要求他尽可能只读的进行调查,禁止修改任何可能导致断网的配置,当有需要我进行验证的时候叫我,最后把调查和修复过程整理成报告,把思考开到 MAX (那会儿 1017 还没发,还不会雷霆大思考),就交给 Agent 去搞了。
Agent 第一步先收集了一遍环境信息,发现我自己部署了 named 作为 DNS 服务器,替代了 OpenWRT 原先使用的 dnsmasq。
这里插播一个背景 对,named 是我部署的,我在 HomeLab 有两台 Windows Server 部署的 DNS 服务器,开启了 AXFR 区域传送,所以为了直接接收 HomeLab 里配置的 DNS 区域信息,我需要一个支持 AXFR 的 DNS 服务器,最终我选择了 bind-utils 里的 named。部署完毕后通过
dig和nslookup进行验证都是可以正常解析到内网和公网域名的,所以我在初步调查的时候虽然怀疑这里,但是没有细想。
Agent 立马对这一块产生了怀疑,所以接下都是对这里进行调查。
发现问题
很快,Agent 就定位到了第一个问题, DNSSEC 报错,并进行了复现验证,原因是国内的 DNS 并没有完整支持 DNSSEC 所以报错了。
报告摘录:
### 2.1 初步检查
确认 `named` 正常运行并监听 53:
ps w | grep named
netstat -lunp | grep ':53 '
发现 `dnsmasq` 配置:
dhcp.@dnsmasq[0].port='0'
生成的配置中:
port=0
dhcp-range=set:lan,192.168.3.100,192.168.3.249,255.255.255.0,12h
**没有 `dhcp-option=6`**。
### 2.2 发现 DNSSEC 报错
`logread | grep named` 中出现大量:
DNS format error from 223.5.5.5#53 resolving xiaomi.com/DS: unrelated SOA ...
deadlock found resolving 'xiaomi.com/DS/IN': 223.5.5.5#53
NOTIMP unexpected RCODE resolving 'xiaomi.net/DS/IN': 114.114.114.114#53
validating com/SOA: got insecure response; parent indicates it should be secure
统计:`format error` 136 条、`deadlock` 191 条(累计 281 条),且在持续新增(30 秒新增 5 条)。
`named.conf` 中并未配置 `dnssec-validation`,而 BIND 9.20 **默认开启**校验;`/var/cache/bind/managed-keys.bind` 中存在根信任锚,确认校验已启用。
### 2.3 A/B 验证(关键)
在不影响生产的前提下,用**独立实例**在 5399 端口启动一份关闭校验的配置:
setsid /usr/sbin/named -u bind -c /tmp/named.test.conf -p 5399 -f -g &
结果:
| 测试 | 生产(校验 ON) | 测试实例(校验 OFF) |
|---|---|---|
| `dnssec-failed.org` | SERVFAIL ×3 | NOERROR ×3 |
| 40 次随机查询 | — | 40/40 成功 |
| 日志中 DS 错误 | 281 条 | **0 条** |
同时确认 `dig @223.5.5.5 xiaomi.com DS` 返回的是**无关的 SOA**(`a.gtld-servers.net`),说明上游确实会破坏 DS 应答。
### 2.4 修复 DNSSEC(第一次变更)
备份后,在 `named.conf` 中加入:
dnssec-validation no;
`named-checkconf` 语法通过,`rndc reload` 生效。验证:
- `dnssec-failed.org` → NOERROR
- 30 秒内新增 DS 错误 = 0
- 默认路由、WAN、HTTPS 均正常
继续调查
DNSSEC 修复后,我验证发现仍然是不通的,所以让 Agent 继续调查,可以注意到在报告的 2.1 节提到了 dnsmasq 的 port 被我配置为了 0,这个是为了让出 53 端口给 named,所以 Agent 就沿着这个配置继续往下调查,期间去阅读了 named 的源码,定位到了根因:
由于我仍然使用 dnsmasq 作为 DHCP 服务器,负责分配 IP 地址,但是当 port 被设置为 0 之后,在下发的 IP 地址中就不再附加 DNS 服务器的 IP 地址了。
修复方式是给 dhcp 手动加上 option,要求下发 DNS 服务器,指向 OpenWRT 的 IP 地址。
报告摘录:
### 2.5 继续追查:音箱为什么仍然不解析?
开启 `named` 查询日志(`rndc querylog on`)观察 60 秒:
- 所有 LAN 客户端都是通过 **IPv6**(`fd13:6baf:c4a2::1`)查询的;
- **192.168.3.164(音箱)查询数为 0**。
检查音箱:
ip neigh show | grep -i c8:bf:4c # 只有 IPv4 邻居,没有 IPv6
**结论:音箱是纯 IPv4 设备**,而 IPv4 的 DNS 只能由 DHCP option 6 提供。
### 2.6 源码确认 DHCP option 6 缺失
dnsmasq 2.93 `src/rfc2131.c` 第 2806 行:
if (daemon->port == NAMESERVER_PORT &&
in_list(req_options, OPTION_DNSSERVER) &&
!option_find2(OPTION_DNSSERVER))
option_put(mess, end, OPTION_DNSSERVER, INADDRSZ, ntohl(context->local.s_addr));
`daemon->port` 只有在 **dnsmasq 自己监听 53** 时才等于 `NAMESERVER_PORT`。设置 `port=0` 后该条件恒为假,**所有 DHCP ACK 都不再携带 DNS 服务器**。
这解释了:
| 设备类型 | 获取 DNS 的途径 | 结果 |
|---|---|---|
| 手机 / 电脑 | IPv6 RDNSS(`fd13:6baf:c4a2::1`) | 正常(所以「上网正常」) |
| 小爱音箱(纯 IPv4) | 本应来自 DHCP option 6 | **缺失 → 无法解析** |
### 2.7 修复 DHCP option 6(第二次变更)
uci add_list dhcp.lan.dhcp_option='6,192.168.3.254'
uci commit dhcp
/etc/init.d/dnsmasq reload
生成的配置确认包含:
dhcp-option=lan,6,192.168.3.254
修复
Agent 修复的最后强制让 小米智能音箱 重新获取 DHCP,我再唤醒 “小爱同学” 进行验证,问题解决。
报告摘录:
### 2.8 强制音箱重新获取 DHCP
音箱在 23:00:45 刚续约过(12h 租约,T1=6h),不会立刻重新获取。对**仅这一台**设备做 Wi-Fi deauth,触发重新连接 + DHCP:
ubus call hostapd.wl0-ap1 del_client \
'{"addr":"c8:bf:4c:f8:a9:f2","deauth":true,"reason":1,"ban_time":0}'
结果(100 秒观察):
t+ 10s wifi=1 lastDHCP=DHCPACK named_queries_from_speaker=19
t+ 40s wifi=1 lastDHCP=DHCPACK named_queries_from_speaker=24
t+100s wifi=1 lastDHCP=DHCPACK named_queries_from_speaker=36
音箱开始正常查询路由器 DNS,解析的正是语音服务域名:
15 speech.ai.xiaomi.com
6 account.ai.xiaomi.com
4 access.speech.ai.xiaomi.com
3 tracker.xiaomixiaoai.com
2 ot.io.mi.com / api2.mina.mi.com / api.ai.xiaomi.com
并建立到小米云(124.251.34.212、27.44.124.195、111.206.191.183:443)的连接。
经验与后续建议
来自 Agent
在 OpenWrt 上把 DNS 交给独立软件(named/AdGuardHome 等)时,必须手动补回 DHCP 的 DNS 下发:
- IPv4:
list dhcp_option '6,<路由器LAN IP>' - IPv6:确认
odhcpd的 RDNSS 正常(本环境默认正常)。 否则纯 IPv4 的 IoT 设备会「看起来网络正常但无法解析」。
- IPv4:
BIND 9.20 默认开启 DNSSEC 校验,而国内公共 DNS 对 DS/NSEC3 支持不完整,容易产生
DNS format error/deadlock .../DS/ 间歇 SERVFAIL。家用场景建议dnssec-validation no;,或改用支持 DNSSEC 的上游。其他纯 IPv4 IoT 设备(雷士灯、Yeelink 灯、电饭煲、网关等)仍持有旧租约,会在下次续约(12h 租约,T1=6h)或断电重连后自动获取新的 DNS 设置;急用可各自断电重启。、
missing expected cookie from 116.116.116.116#53属于上游不支持 DNS Cookie 的提示,非错误,可忽略。
附录:本次使用的关键诊断命令
# 服务与监听
ps w | grep -E 'named|dnsmasq'
netstat -lunp | grep ':53 '
rndc status
# DHCP 实际下发内容
grep -E 'dhcp-option|dhcp-range' /var/etc/dnsmasq.conf.*
# 查询日志
rndc querylog on
logread | grep 'query:' | grep '<客户端IP>'
rndc querylog off
# DNSSEC 校验是否生效(A/B 对照)
dig @127.0.0.1 dnssec-failed.org A
dig @223.5.5.5 xiaomi.com DS
# 日志中的 DNSSEC 故障
logread | grep -i named | grep -E 'format error|deadlock|validating|NOTIMP'
# 设备定位
cat /tmp/dhcp.leases
ubus call hostapd.wl0-ap1 get_clients
ip neigh show dev br-lan
cat /proc/net/nf_conntrack | grep '<客户端IP>'
# 配置语法检查
named-checkconf /etc/bind/named.conf