すべてのプロダクト
Search
ドキュメントセンター

Alibaba Cloud DNS:iOS で DNS 名前解決時間と LocalDNS の名前解決結果を取得するためのガイド

最終更新日:Nov 09, 2025

このドキュメントでは、iOS でネットワークリクエストを行う際に DNS 解決時間と LocalDNS 解決結果を取得する方法について説明します。

1. 概要

iOS での標準的なネットワークリクエストの場合、NSURLSessionDelegate のデリゲートメソッドから LocalDNS の名前解決時間を取得できます。HTTPDNS ソフトウェア開発キット (SDK) を統合している場合、SDK は LocalDNS をバイパスしてドメイン名の名前解決を行います。この場合に DNS 名前解決時間を取得するには、SDK の名前解決 API を呼び出す前後のタイムスタンプを取得し、その差を計算します。

iOS では、getaddrinfo メソッドを使用して、ローカル DNS の解決結果を取得できます。これらを想定される解決結果と比較して、ハイジャックが発生しているかどうかを判断できます。

2. DNS 解決時間を取得する方法

  • ネットワークリクエストインターフェイスが https://domain/path 形式を使用している場合は、次のコードを参照して DNS 解決時間を取得できます。

  • 説明

    iOS 14 のネイティブ暗号化ソリューションを使用してカスタム DNS を設定している場合、以下のコードを使用して取得される DNS 解決時間は、カスタム DNS の解決時間になります。使用していない場合、取得される DNS 解決時間は LocalDNS の解決時間になります。

#pragma mark URLSession Delegate
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics {
    if ([metrics.transactionMetrics count] <= 0) return;
    [metrics.transactionMetrics enumerateObjectsUsingBlock:^(NSURLSessionTaskTransactionMetrics *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) {
        if (obj.resourceFetchType == NSURLSessionTaskMetricsResourceFetchTypeNetworkLoad) {
            NSLog(@"%@",[NSString stringWithFormat:@"リクエスト URL:%@",[obj.request.URL absoluteString]]);
            NSLog(@"%@",[NSString stringWithFormat:@"サーバー IP:%@",obj.remoteAddress]);

            NSURLSessionTaskMetricsDomainResolutionProtocol dnsProtocol = obj.domainResolutionProtocol;
            NSLog(@"%@",[NSString stringWithFormat:@"DNS タイプは %ld です", (long)dnsProtocol]);
            NSLog(@"%@",[NSString stringWithFormat:@"0:不明、1:UDP、2:TCP、3:TLS、4:HTTPS"]);
            if (obj.domainLookupStartDate && obj.domainLookupEndDate) {
                int dnsLookupTime = ceil([obj.domainLookupEndDate timeIntervalSinceDate:obj.domainLookupStartDate] * 1000);
                NSLog(@"%@",[NSString stringWithFormat:@"DNS 開始時間: %@、DNS 終了時間: %@", obj.domainLookupStartDate, obj.domainLookupEndDate]);
                NSLog(@"%@",[NSString stringWithFormat:@"DNS 解決時間(ミリ秒): %d",dnsLookupTime]);
            }
        }
    }];
}
  • HTTPDNS SDK を統合している場合、次のコードを使用して HTTPDNS SDK からドメイン名の名前解決時間を取得します。

CFTimeInterval startTimer = CACurrentMediaTime();
//使用している SDK の解決メソッドに置き換えてください
[[DNSResolver share] getIpv4DataWithDomain:@"main.m.taobao.com" complete:^(NSArray<NSString *> *dataArray) {
    CFTimeInterval endTimer = CACurrentMediaTime();
    UInt32 rtt = (endTimer - startTimer) * 1000;
    NSLog(@"%@",[NSString stringWithFormat:@"DNS 解決時間(ミリ秒): %d",rtt]);                   
}];

3. LocalDNS 解決結果の取得とハイジャック検出比較の実行

次のコードを使用して、LocalDNS 解決結果を取得し、想定される解決結果と比較して、ハイジャックが発生しているかどうかを判断できます。

#import <Foundation/Foundation.h>
#import <netdb.h>
#import <arpa/inet.h>

- (void)resolveDomain:(NSString *)domain expectedIPs:(NSArray<NSString *> *)expectedIPs {
    struct addrinfo hints, *result, *p;
    memset(&hints, 0, sizeof(hints));

    // hints 構造体を初期化します
    hints.ai_family = AF_UNSPEC; // IPv4 または IPv6
    hints.ai_socktype = SOCK_STREAM; // TCP
    
    // DNS クエリを実行します
    int s = getaddrinfo([domain UTF8String], NULL, &hints, &result);
    if (s != 0) {
        NSLog(@"getaddrinfo エラー: %s", gai_strerror(s));
        return;
    }

    BOOL isHijacked = NO;

    // 結果をトラバースして IPv4 アドレスと IPv6 アドレスを取得します
    for (p = result; p != NULL; p = p->ai_next) {
        char ipBuffer[INET6_ADDRSTRLEN]; // IP アドレスをフォーマットするためのバッファ
        if (p->ai_family == AF_INET) {
            struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
            inet_ntop(AF_INET, &ipv4->sin_addr, ipBuffer, sizeof(ipBuffer));
            NSLog(@"IPv4 アドレス: %s", ipBuffer);
        } else if (p->ai_family == AF_INET6) {
            struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
            inet_ntop(AF_INET6, &ipv6->sin6_addr, ipBuffer, sizeof(ipBuffer));
            NSLog(@"IPv6 アドレス: %s", ipBuffer);
        }

        // 解決結果を想定される IP アドレスと比較します
        if (![expectedIPs containsObject:[NSString stringWithUTF8String:ipBuffer]]) {
            isHijacked = YES;
        }
    }

    // ハイジャックが存在するかどうかを判断します
    if (isHijacked) {
        NSLog(@"警告: DNS ハイジャックが存在する可能性があります!");
    } else {
        NSLog(@"DNS ハイジャックは検出されませんでした。");
    }

    // メモリを解放します
    freeaddrinfo(result);
}