前言
最近有海外地区的用户反馈无法访问公司的网络,无法下载应用和系统进行升级。了解到浏览器可以正常访问公司域名,谷歌,油管等都能正常使用。日志分析GET请求服务器数据时没有得到应答,最终查询网络相关修改确认与网络IPV6有关。
先来看下全球主流网站IPv6的支持情况:
具体可查看这篇文章:https://zhuanlan.zhihu.com/p/605189137?utm_id=0
可以看到全球主流大公司很多未支持IPv6网络,国内阿里、腾讯也是部分支持并未全部支持,而360、百度、淘宝、CSDN等网站都不支持IPv6。
不止要考虑网站的IPv6的支持,还要考虑电信业务商是否支持IPv6。像台湾有些电信业务商,支持IPv6网络,例如台湾之星、中华电信,且在4G和5G的支持情况也不一致。
IPv6的可达性测试
在测试IPv6的可达性网址https://en.internet.nl/ 测试 www.czvv.com 网址结果如下,提示IPv6不可达。
同样测试国内百度www.baidu.com 和 www.tecent.com 也是IPv6不可达。
测试支付宝www.alipay.com 谷歌www.google.com 或者 www.youtube.com 等都是IPv6可达的。
总的来说国内IPv6的普及率不高,很多网址都是IPv6不可达。
问题分析
湾湾和阿三等地区用户都反馈了无法进行在线检查升级,一直在等待服务器应当。湾湾用户反馈使用台湾之星的手机卡不能检测升级,而换另一张非台湾之星的手机卡可以检测升级,之前系统未升级时可以正常访问网络的。通过查证得知系统添加修改了DNS对IPv6的支持,因此可知系统支持IPv6后无法正常从公司服务器获取数据。系统支持IPv6后会优先使用IPv6的地址进行访问。
为了进一步去除IPv6的影响,让湾湾用户在手机上关闭了IPv6的支持,只使用IPv4。结果关掉IPv6后即可以正常检测升级了。
从抓取的日志看到开启IPv6的情况下,请求www.czvv.com 获取信息时一直未收到服务器应答,显示www.czvv.com 使用IPv6的地址不可达。
解决方案
由于IPv6地址不可达,因此需要对DNS进行过滤,滤除IPv6地址。
OkHttpClient
支持设置自定义DNS,于是在网络框架初始化时配置OkHttpClient
,并添加自定义的DNS过滤器。
DnsFilter
代码如下:
import androidx.annotation.NonNull;import com.czvv.base.utils.ALog;
import com.czvv.mycar.util.ShareDb;import okhttp3.Dns;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;public class DnsFilter implements Dns {public DnsFilter() {}@NonNull@Overridepublic List<InetAddress> lookup(@NonNull String hostname){List<InetAddress> addresses = new ArrayList<>();try {List<InetAddress> list = Dns.SYSTEM.lookup(hostname);if (ShareDb.getDnsFilter()) {for (InetAddress inetAddress : list) {ALog.print("inetAddress:" + inetAddress.toString() + " " + (inetAddress instanceof Inet6Address));if (inetAddress instanceof Inet4Address) {addresses.add(inetAddress);}}} else {return list;}} catch (UnknownHostException e) {e.printStackTrace();}return addresses;}
}
通过遍历系统的DNS地址列表,把IPv6的地址滤去。这样去请求网络的时候就不会使用IPv6地址去访问了。
通过增加DNS过滤开关进行过滤IPV6地址,应对不同地区的网络环境导致的网络问题。