事情的起因是家里的安卓设备经常刷带有图片流的 APP 卡顿,怀疑是家里配置的 IPv6 的问题,于是花了一天时间利用现成的工具研究一下,但是似乎还是没有定位出结果,整理发出来请大家帮忙分析一下。
反复开关安卓设备的 wifi 开关,然后刷 ipv6 的网页资源 testipv6.cn ,会偶发提示没有接入 IPv6 的现象,然而此时安卓设备 wifi 详情页面是有全球唯一 IPv6 地址的。
ER-X (拨号,IPv6-PD 下发,SLAAC 配置方式)
|
|
TP-Link WDR7650 ( AP 模式,有线连接 ER-X ,为下面设备提供无线接入)
《 》
《 》
Android (Honor) Mac
在 ER-X 路由器处抓包发现,安卓设备以全球唯一 IPv6 地址向目标服务器发送了 TCP 请求,但是回程数据包经由路由器转发时,被路由器直接丢弃,并向目标服务器返回目标不可达 ICMPv6 报文。
进一步分析发现,路由器在转发 IPv6 报文给安卓设备前,需要先通过 Neighbor Discovery Protocol 获得设备的 MAC 地址。但是,路由器反复以多播方式发送 Neighbor Solicitation ( NS ),但是安卓节点却迟迟不回应 Neighbor Advertisement ( NA )报告自己的 MAC 地址,导致路由器以为目的节点不可达,从而导致路由器直接丢包。这也解释了加载图片卡的原因:安卓设备收不到 ipv6 数据包,从而超时,然后使用 ipv4 。
苹果设备支持较好,每次路由器的 NS 报文,均有设备端的 NA 报文回复。
安卓设备端丢弃或者不回应 NS 报文。 Google 发现参考来源[1],[2],有类似的安卓设备不回应 Neighbor Solicitation 的情况:
The problem was the WiFi driver. Samsung for some reason thought it should block ICMPv6/NDP in standby to safe battery.
无线 AP 对于有线以太网的组播报文转到无线空口时可能丢弃。 Google 发现,无线网卡的驱动对于多播报文的处理可能不尽相同,可能处于安全或者性能考虑丢弃多播报文。
抓包发现,这台无线路由器疑似使用了多播转单播技术,如下图所示: 根据参考来源[3]:
Many vendors of wireless APs support multicast-to-unicast conversion, which sends a unicast copy the frame to each intended receiver, using IGMP snooping to determine those stations. This means that the frame can be sent at the receiving station’s best data rate, which should almost always be above the minimum. Several unicast transmissions at 54Mbps would still use less channel time than the same multicast transmission at 1Mbps. In addition, stations which aren’t the intended receivers don’t need to wake up to listen to the frame, reducing their battery consumption.
无线路由器可能使用了 IGMP snooping 技术,而这可能导致不转发 IPv6 的组播报文。安卓设备在退出再加入无线网络时,路由器向安卓设备发起了 IGMP Query 查询,但是安卓设备并没有回应,也没有主动报告过。这说明,无线路由器获得网络中的所有节点不是通过多播来进行查询的。因为网络中的节点肯定不是全部都支持多播,且本身接入无线网络就已经报告了自己的 MAC ,无需多此一举。但是,这里仍然存在 bug 的可能,就是由于节点没有报告自己的状态,snooping 可能阻止报文向此节点的传播。
与参考来源[4]类似的情况,我们在出现问题后,让安卓设备 ping 路由器 WAN 口地址,过一段时间后安卓设备就有 IPv6 网络访问了,发现也即是安卓设备发出了 NA 报文回应路由器的 NS 报文。
安卓不回应路由器的 NS 报文,直到第 28 个 ping 报文发出,才回应路由器的 NS:
由于安卓设备没有 Root ,不能直接在上面抓包,只能将问题缩小到安卓设备和无线 AP 上了。由于没有一个比较好的方法继续分析和解决,就暂时关闭 IPv6 了,为了给家里人用得更加稳定(家里安卓设备居多)。大家如果感兴趣可以一起交流,帮忙楼主分析一下。
[^1]. https://forums.he.net/index.php?topic=4069.0
[^2]. https://forums.he.net/index.php?topic=2268.0
[^3]. https://wirelesslywired.com/2019/05/02/multicast-over-wireless/
[^4]. https://l2dy.sourceforge.io/2021/05/11/openwrt-ipv6-relay.html
1
ouqihang 272 天前
用了几年的 TPLINK MESH 最近也感觉不好,有手机不能自动漫游,图片也有加载不出的情况,有线电脑还好。
ipv6 ,开放所以防火墙有些网站打不开,定位到 MSS 钳制问题,用了命令 ip6tables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu 解决。 |
2
pengyoukun OP @ouqihang 之前我也以为是 MSS 钳制的问题,也试过在 ER-X 上配置过,但是问题没有彻底解决。(还有因为宽带被运营商踢掉导致周期性内网的 ipv6 地址不更新导致的断网问题)。今天抓包才发现了这个新情况,这个 IPv6 配置起来真的比 v4 复杂太多了。
|
3
oovveeaarr 272 天前
看到 LZ 的历史发帖,盲猜是升级了 HyperOS 的手机。
这是 HyperOS 新升级出来的 BUG ,(不清楚最新版 MIUI 有没有)和其他设备都没啥关系,上个月已经提给官方了,说已经反馈上去了,不知道具体结果怎么样。 解决方法就是飞行模式多几次,就可以了。 仔细观察下的话其实可以发现,系统注册了两个 IPv6 (这是预期现象) 一种一个 IPv6 (主 IP )是通的,另外一个 IPv6 ( privacy ip )不通。而系统默认只能使用不通的那个 IP 去连接,导致了这个问题。 原因就是 LZ 检查的那样,其中一个 IP ND 不完整。 |
4
oovveeaarr 272 天前
才看到 LZ 可能是 Honor 设备,不会是 Android 14 的问题吧?
用了好多年 IPv6 了,只在最近的 HyperOS 上遇到符合 LZ 描述的这个问题。也可能不是一个问题,但是原因都是一样的) |
5
defaw 272 天前
你可以用 gopacket 这个库以比较简单的代码用写一个 ndp 代理出来,请求路由器 api 获取手机的 ip ,然后替手机回应 ns 报文。用我写的这个 https://github.com/yu1745/ndp_proxy 改几行就能用
|
6
oovveeaarr 272 天前
@oovveeaarr #3 如果有路由权限的话,可以手动 flush 下 neigh ,会发现主 IP 依然能够正常重新发现,但是副 IP 就。。。
|
7
pengyoukun OP @oovveeaarr 对的,家里人用的华为荣耀系列手机比较多,楼主测试时用的是荣耀,android 14 。
根据微软提的隐私扩展,确实是默认用 privacy ip 进行连接。但是这个 neighbor 不完整看来小米系列也有这类问题哈? 设备不回应 NS 报文就没有办法建立邻居。这个问题比较偶发,感觉应该是什么地方的一个 bug 。 |
8
pengyoukun OP @defaw 有道理,非常感谢你的魔改建议。你也遇到过类似的情况吗(应该确定是手机设备的问题了嘛)?
|
9
dude4 272 天前
建议撸主换一台安卓设备,然后就可以确定是·安·卓的问题,还是某个厂商安卓·ROM 的问题
当然安卓本身 V6 就很操蛋,只支持 SLAAC ,,,,,, |
10
rick13 272 天前
我家里现在就是这样,我妈的红米手机在有 ipv6 地址的情况下网络很差,快手购物车都刷不出来,网络加载资源也慢,我根据 mac 地址把 ipv6 流量给 drop 了,算是缓解
|
11
oovveeaarr 272 天前
@pengyoukun #7 只要是用 SLAAC 的话,默认就会获取多个 IP 做隐私保护。如果 LZ 你说的隐私扩展指的 EUI-64 地址生成,这个只能在有 root 权限的情况下关闭。
如果是 Temporary/Privacy IP ,有个变通方法是放弃 SLAAC 改用 DHCPv6 ,但是 Android 又不支持 DHCPv6……。 我从 Android 8/9 开始使用 IPv6 ,到目前为止只有在基于 Android 14 的 HyperOS 遇到过这个问题,前几天也有其他群友在这个条件下遇到过相同的问题。 如果 LZ 在其他基于 Android 14 的 ROM 中也遇到了这个问题,可能 Android 14 本身的问题可能性会更高一些了? |
12
pengyoukun OP @oovveeaarr 感谢层主的分析和线索,我刚刚也用"android 14" ipv6 去 google 了一下,确实有一些类似的情况。
一加: https://www.reddit.com/r/ipv6/comments/17wp3a6/android_lose_ipv6_on_wifi/ 然后 google 在 android 14 preview 也提到了类似安卓设备不发送 RA 报文导致 ipv6 连接丢失的情况,并说已经修复了。。。(结果现在是 NA 报文不发了)并且说也不仅仅是 14 的问题,以前也存在过类似的,原因很复杂和 AP 配置、省电模式都有关系。 (参考链接: https://issuetracker.google.com/issues/290008647 ) 给出的参考建议可能是,增大路由器 ipv6 邻居更新表的时间,不要太早就把设备失效。也算一个权宜之计吧。和 5#的建议相同,都是想办法把路由器的 ipv6 邻居表保持存活。 |
13
kxy09 260 天前
还以为 miui 又作妖了,结果是通病,现在动不动就要重新开关 wifi
|
14
L0lita 245 天前
妈的 Google 的 bug 关随机 mac 关 IGMP Snooping 关 WMM APSD 关 160Mhz 锁定频道 又是断流 又是丢 ipv6 把本宫折腾的够呛
|
15
pengyoukun OP @L0lita 真的头疼,现在 ipv6 主流流量还是移动数据网贡献的多,感觉 wifi 这个最后一公里问题和坑都很大。。。
https://www.china-ipv6.cn/#/usersInfo/simpleInfo |
16
fugu37 100 天前
我遇到的问题更直接,息屏一段时间再打开,来自 WIFI 的 IPv6 地址直接消失了。
上游找到一个 issue ,和我遇到的现象一模一样: https://issuetracker.google.com/issues/241959699 最后也只是建议增加 DTIM 、延长 SLAAC 有效期,然后期待问题消失。 |
17
fugu37 100 天前
@fugu37 #16 issuetracker 里给出的参数都没用,系统更新 3 个小版本,问题消失。
本就是 Android 为了省电强制过滤 NDP 引入的问题,解决问题还是要回归到操作系统本身。 |
18
xiaofami 52 天前 via Android
@fugu37 我在红米 K30U 和 iqoo neo 7 上都会遇到该问题,通过 ipv6 连接到群晖 NAS ,息屏备份照片一段时间后连接就会中断,发现 Global ipv6 地址没了,只能手动切换 WIFI 开关
|
19
pengyoukun OP 近期看到 Issue Tracker 又有新的类似提问了,https://issuetracker.google.com/issues/347584783 ,设计初衷是为了省点电,看来这个问题的解决需要 WiFi 设备商来处理了
引用回答给自己留一个解决思路: increasing access point dtim interval to 6 ; increasing lifetime of all fields in RA (router, dns, route, etc lifetimes); making RA lifetime >15x RA advertisement interval frequency ; disabling igmp/mld snooping ; enabling multicast to unicast conversion |