wireshark抓包ip地址显示格式是ipv6而不是ipv4

问题:抓包显示Source和Destination的IP都是ipv6的而不是ipv4的
079
所以怀疑 Android 端解析域名时解析到两个 IP 后(ipv4和ipv6),优先使用 IPV6 连接的后端服务

文章目录

验证

使用如下代码,验证 DNS 解析的 IP 地址

try {
   InetAddress[] inetAddresses = InetAddress.getAllByName("server.xxxx.cn");
   for(InetAddress inetAddress : inetAddresses){
     System.out.println(inetAddress.getHostAddress());
   }
} catch (UnknownHostException e) {
   e.printStackTrace();
}
log显示:解析到了 ipv6 和 ipv4 两个 ip 地址,且 ipv6 一直是首个 ip 地址

解决

通过上面的验证,基本断定,Android 端通过 ipv6 连接的服务地址。
端的 http client 库为 okhttp , 查看 javadoc 后,提供了 DNS 接口,代码如下:

image 10

我们通过实现此接口,将解析到的 ip 顺序调整一下,如果是 ipv4 则将其放到数据的第一个,其它保持不变,如下:

package com.grandstream.cmcc.contacts.http;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import okhttp3.Dns;

public class XDns implements Dns {
public XDns() {
}

@Override
public List<InetAddress> lookup(final String hostname) throws UnknownHostException {
if (hostname == null) {
throw new UnknownHostException("hostname == null");
} else {
try {
List<InetAddress> list = Arrays.asList(InetAddress.getAllByName(hostname));
List<InetAddress> inetAddressList = new ArrayList<InetAddress>();
InetAddress[] inetAddresses = InetAddress.getAllByName(hostname);
for(InetAddress inetAddress:inetAddresses) {
if (inetAddress instanceof Inet4Address) {
inetAddressList.add(0, inetAddress);
} else {
inetAddressList.add(inetAddress);
}
}
return inetAddressList;
} catch (Exception var4) {
UnknownHostException unknownHostException =
new UnknownHostException("Broken system behaviour for dns lookup of " + hostname);
unknownHostException.initCause(var4);
throw unknownHostException;
}
}
}
}

修改 okhttp 的 dns 解析类,如下:

OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.dns(new XDns());
OkHttpClient client = builder.build();

再次测试,发现 ip地址格式变成了ipv4

image 12

备注

  1. 在测试过程中,发现中国移动和中国电信的 4G 网络 DNS 解析都会解析到两个 IP 地址,而中国联通的 4G 网络只能解析到 ipv4 的址,手机型号是小米 note3
  2. 网上很多的方案都是将 ipv6 关掉,或者在 appstore 审核时打开,审核完成后再关掉,这种不能解决根本问题的方法实在不可取,大家一定要仔细分析,擦亮眼睛

借鉴该博客

4+

留下评论