安卓设备疑似在 WiFi 下 IPv6 工作不正常,导致偶发加载卡顿

31次阅读

共计 2169 个字符,预计需要花费 6 分钟才能阅读完成。

事情的起因是家里的安卓设备经常刷带有图片流的 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 路由器抓包分析

在 ER-X 路由器处抓包发现,安卓设备以全球唯一 IPv6 地址向目标服务器发送了 TCP 请求,但是回程数据包经由路由器转发时,被路由器直接丢弃,并向目标服务器返回目标不可达 ICMPv6 报文。

进一步分析发现,路由器在转发 IPv6 报文给安卓设备前,需要先通过 Neighbor Discovery Protocol 获得设备的 MAC 地址。但是,路由器反复以多播方式发送 Neighbor Solicitation(NS),但是安卓节点却迟迟不回应 Neighbor Advertisement(NA)报告自己的 MAC 地址,导致路由器以为目的节点不可达,从而导致路由器直接丢包。这也解释了加载图片卡的原因:安卓设备收不到 ipv6 数据包,从而超时,然后使用 ipv4。

Mac 抓包分析

苹果设备支持较好,每次路由器的 NS 报文,均有设备端的 NA 报文回复。

问题可能的原因

  1. 安卓设备端丢弃或者不回应 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.
    
  2. 无线 AP 对于有线以太网的组播报文转到无线空口时可能丢弃。
    Google 发现,无线网卡的驱动对于多播报文的处理可能不尽相同,可能处于安全或者性能考虑丢弃多播报文。

    抓包发现,这台无线路由器疑似使用了多播转单播技术,如下图所示:
    安卓设备疑似在 WiFi 下 IPv6 工作不正常,导致偶发加载卡顿
    根据参考来源[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:
安卓设备疑似在 WiFi 下 IPv6 工作不正常,导致偶发加载卡顿

小结

由于安卓设备没有 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

正文完
 0