All Products
Search
Document Center

Alibaba Cloud DNS:Obtain DNS resolution duration and resolution results of local DNS servers by using the OkHttp library on an Android app

Last Updated:Nov 11, 2024

This topic describes how to obtain Domain Name System (DNS) resolution duration when you execute network requests by using the OkHttp library on an Android app.

1. Overview

You can use EventListener to obtain DNS resolution duration when you execute network requests by using the OkHttp library on an Android app. EventListener provides multiple callback methods to track network requests at different phases, including DNS resolution, connection establishment, and data transmission.

You can use InetAddress.getAllByName(String host) to obtain the DNS resolution resolution of local DNS servers. This allows you to determine whether domain hijacking occurs by comparing the obtained resolution with the expected resolution.

2. Procedure

You can perform the following steps to use OkHttp and EventListener to obtain DNS resolution duration:

Step 1: Import the OkHttp library

Add the OkHttp dependency in the build.gradle file.

implementation 'com.squareup.okhttp3:okhttp:4.9.3'

Step 2: Create a custom EventListener class

Create a custom EventListener class to listen to and record DNS resolution duration.

import okhttp3.EventListener;
import okhttp3.Call;
import okhttp3.HttpUrl;

public class DnsTimingEventListener extends EventListener {
    private long dnsStartTime;
    private long dnsEndTime;

    @Override
    public void dnsStart(Call call, String domainName) {
        super.dnsStart(call, domainName);
        dnsStartTime = System.currentTimeMillis();
    }

    @Override
    public void dnsEnd(Call call, String domainName, List<InetAddress> inetAddressList) {
        super.dnsEnd(call, domainName, inetAddressList);
        dnsEndTime = System.currentTimeMillis();
        long dnsDuration = dnsEndTime - dnsStartTime;
        System.out.println("DNS resolution duration: " + dnsDuration + "Milliseconds");
    }
}

Step 3: Create an OkHttpClient instance and configure the EventListener.Factory parameter

Configure the custom EventListener.Factory parameter for the OkHttpClient instance.

import okhttp3.OkHttpClient;

// Create an OkHttpClient instance.
OkHttpClient client = new OkHttpClient.Builder()
        .eventListenerFactory(new EventListener.Factory() {
            @Override
            public EventListener create(Call call) {
                return new DnsTimingEventListener();
            }
        })
        .build();

Step 4: Execute a network request

Execute a network request by using the configured OkHttpClient instance.

import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;

public void executeNetworkRequest() {
    // Create a Request object.
    Request request = new Request.Builder()
    // Enter an actual URL in .url() 
            .url("https://www.example.com")
            .build();

    try {
        // Execute the request.
        Response response = client.newCall(request).execute();
        // Process the response.
        if (response.isSuccessful()) {
            System.out.println("The request is successful");
            // You can process the response here.
        } else {
            System.out.println("The request failed, Status code:" + response.code());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

You can perform the preceding steps to obtain DNS resolution duration and process the response. This can not only help you understand the periods of time consumed by network requests but also can be used for performance improvement and monitoring.

If you have integrated Alibaba Cloud Public DNS SDK with your Android app that uses the OkHttp library, you can obtain the DNS resolution duration of Alibaba Cloud Public DNS by performing the preceding steps. If you have not integrated Alibaba Cloud Public DNS SDK with your Android app that uses the OkHttp library, you can obtain only the DNS resolution duration of local DNS server InetAddress by performing the preceding steps.

The following sample code provides an example on how to access Alibaba Cloud Public DNS SDK on Android apps that use OkHttp :

   public class OkHttpDns implements Dns {

    private static OkHttpDns instance;
    private static Object lock = new Object();
    private DNSResolver mDNSResolver = DNSResolver.getInstance();

    private OkHttpDns() {
    }

    public static OkHttpDns getInstance() {
        if (null == instance) {
            synchronized (lock) {
                if (instance == null) {
                    instance = new OkHttpDns();
                }
            }
        }
        return instance;
    }

    @Override
    public List<InetAddress> lookup(@NonNull String hostname) throws UnknownHostException {
        //Call the API operation in Alibaba Cloud Public DNS SDK for Android to resolve a domain name.
        String ip = null;
        String[] ipv4Array = mDNSResolver.getIpv4ByHostFromCache(hostname,true);
        if (ipv4Array != null && ipv4Array.length > 0) {
            ip = ipv4Array[0];
        }else {
            ip = mDNSResolver.getIPV4ByHost(hostname);
        }

        if (ip != null) {
            //If the returned ip value is not null, directly use the IP address to send network requests.
            Log.d(TAG, "mDnsCache IP: " + ip);
            return Arrays.asList(InetAddress.getAllByName(ip));
        }
        //If null is returned, use the system DNS service to resolve the domain name.
        return Dns.SYSTEM.lookup(hostname);
    }
}

3. Obtain the DNS resolution result of local DNS servers and determine whether domain hijacking occurs

The following sample code provides an example on how to obtain DNS resolution duration of local DNS servers:

public List<String> getIPAddresses(String domain) {
    List<String> ipAddresses = new ArrayList<>();
    try {
        InetAddress[] addresses = InetAddress.getAllByName(domain);
        for (InetAddress address : addresses) {
            ipAddresses.add(address.getHostAddress());
        }
    } catch (UnknownHostException e) {
        e.printStackTrace();
    }
    return ipAddresses;
}

The following sample code provides an example on how to determine if domain hijacking occurs by comparing the obtained DNS resolution duration of local DNS servers with the expected duration:

public boolean isDnsHijacked(String domain, List<String> expectedIps) {
      List<String> localIps = getIPAddresses(domain);
      if (localIps.isEmpty()) {
          return false; //  Domain name cannot be resolved.
      }
      for (String localIp : localIps) {
          if (!expectedIps.contains(localIp)) {
              return true; // The unexptected IP address indicates that DNS may be hijacked.
          }
      }
      return false; // All DNS resolutions match the expected duration.
  }