现象是什么
家里网络最近是这样:国外网站都正常,国内 App 却卡。手机在家里 WiFi 下刷抖音,视频要等半天才出来,评论区头像和图片更慢;电脑浏览器打开国内站也转圈。同一台手机切到流量就正常,切回主路由也正常——问题只出在旁路由这条路上,而且不是断网,是“能打开、但慢”。
整体网络配置
先把家里的配置说清楚,后面的问题就出在这里。
主路由:Padavan,负责拨号和 DHCP,局域网网关。
旁路由:一台跑在 NAS 虚拟机上的 OpenWrt(ImmortalWrt),1 核 1GB,单臂、只有一个网口。主路由的 DHCP 把网关和 DNS 都指向旁路由,所以设备上网先经过旁路由,再出去。
- 旁路由本身不开 DHCP,IPv4 的地址分配还留在主路由;
- 流量分流用 PassWall,模式是“中国列表以外”走代理,国内直连,代理是 Xray,多个节点自动切换;
- DNS 走旁路由上的 AdGuard,上游是本地的 chinadns 分流,国内域名走国内解析,国外走可信解析;
- AdGuard 的过滤是开着的,AdGuard DNS 过滤列表在用。
关键的一点是:这套配置里,旁路由实际能走通的只有 IPv4。它自己没有公网 IPv6 地址,也没有到公网的 IPv6 默认路由,家里设备能用的 IPv6 通路,本来就不应该经过它。
为什么会导致这个问题
问题就出在旁路由明明没有公网 IPv6,却还在 IPv6 上插了两脚。
第一脚:广播自己是 IPv6 路由。
旁路由上的 odhcpd 默认开着 IPv6 路由广播。注意一个坑:旁路由的 DHCP 是关着的,但这只关了 IPv4 的地址分配,IPv6 的路由广播并没有跟着关。于是局域网里同时有两份 IPv6 路由广播,设备一旦把旁路由当成 IPv6 网关,IPv6 数据发过去,旁路由根本不知道往哪送,只能丢掉,App 等超时再退回 IPv4——表现出来就是卡顿、转圈。
国内 App 现在很多都优先 IPv6,全撞上了;国外流量走的是代理的 IPv4,根本不经过这条 IPv6 的坑,所以国外正常、国内卡。
第二脚:DNS 返回 IPv6 地址。
旁路由的 DNS 会同时返回 IPv4 和 IPv6 地址,手机优先用 IPv6。图片域名的 IPv6 节点是移动那边的,视频域名的 IPv6 节点是电信那边的,图片跑到跨运营商的节点上就慢,视频跑到同运营商的节点上就快。再加上图片是几十张小文件,每张都要单独解析、握手、排队,视频是一条长连接摊薄了这些代价,所以“图片比视频慢”并不是网速问题。
怎么处理的
只动了旁路由上的两处,别的全没动,主路由也不用改。
第一处:关掉 IPv6 路由广播。
把 odhcpd 的 IPv6 路由广播关掉,重启生效。IPv4 网关、代理、去广告都不动。改完手机切回旁路由、开关一次 WiFi 清掉旧路由再测,视频就恢复正常了。回滚也简单,把广播再改回开着就行。
第二处:让 DNS 不再返回 IPv6 地址。
打开 AdGuard 里的 aaaa_disabled,重启生效。这样旁路由的 DNS 只给 IPv4 地址,所有设备都只走 IPv4,手机也不用再手动设 DNS。改完验证过:问图片域名要 IPv6 地址返回是空的,要 IPv4 地址正常返回。
现在的状态
视频正常,图片普遍快了很多。个别图片还稍微慢一点,那已经不是黑洞式的故障了,主要是图片节点本身有远近冷热之分,加上评论区几十张图同时抢、排队,以及旁路由这一跳每张小图都要多付一次转发和握手的代价——这是旁路由方案本身的一点正常代价,再往下抠收益不大。
一句话总结
单臂旁路由如果没有公网 IPv6,就要把 IPv6 关干净:路由广播、DNS 的 IPv6 地址都要一起处理,只关 DHCP 是不够的,留任何一处,设备都会在 IPv6 上摔一跤。