このトピックでは、AndroidアプリでOkHttp
ライブラリを使用してネットワークリクエストを実行するときに、ドメインネームシステム (DNS) 解決期間を取得する方法について説明します。
1. 概要
AndroidアプリでOkHttp
ライブラリを使用してネットワークリクエストを実行するときに、EventListener
を使用してDNS解決期間を取得できます。 EventListener
は、DNS解決、接続確立、データ送信など、さまざまなフェーズでネットワーク要求を追跡するための複数のコールバックメソッドを提供します。
InetAddress.getAllByName(String host)
を使用して、ローカルDNSサーバーのDNS解決解決を取得できます。 これにより、取得した解像度と予想される解像度を比較して、ドメインハイジャックが発生したかどうかを判断できます。
2. 手順
OkHttp
とEventListener
を使用してDNS解決期間を取得するには、次の手順を実行します。
手順1: OkHttp
ライブラリのインポート
build.gradle
ファイルにOkHttp
依存関係を追加します。
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
手順2: カスタムEventListener
クラスを作成する
DNS解決期間をリッスンして記録するカスタムEventListener
クラスを作成します。
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");
}
}
手順3: OkHttpClient
インスタンスを作成し、EventListener.Factory
パラメーターを設定します。
OkHttpClient
インスタンスのカスタムEventListener.Factory
パラメーターを設定します。
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();
ステップ4: ネットワーク要求を実行する
設定されたOkHttpClient
インスタンスを使用してネットワークリクエストを実行します。
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();
}
}
上記の手順を実行して、DNS解決期間を取得し、応答を処理できます。 これは、ネットワークリクエストによって消費される期間を理解するのに役立つだけでなく、パフォーマンスの向上と監視にも使用できます。
Alibaba Cloud Public DNS SDKをOkHttp
ライブラリを使用するAndroidアプリと統合している場合、上記の手順を実行することで、Alibaba Cloud Public DNSのDNS解決期間を取得できます。 Alibaba CloudパブリックDNS SDKをOkHttp
ライブラリを使用するAndroidアプリと統合していない場合、上記の手順を実行することで、ローカルDNSサーバーInetAddress
のDNS解決期間のみを取得できます。
次のサンプルコードは、OkHttp
を使用するAndroidアプリでAlibaba Cloud Public DNS SDKにアクセスする方法の例を示しています。
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. ローカルDNSサーバーのDNS解決結果を取得し、ドメインハイジャックが発生するかどうかを判断する
次のサンプルコードは、ローカルDNSサーバーのDNS解決期間を取得する方法の例を示しています。
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;
}
次のサンプルコードでは、取得したローカルDNSサーバーのDNS解決期間を予想期間と比較して、ドメインハイジャックが発生したかどうかを判断する方法の例を示します。
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.
}