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

Alibaba Cloud DNS:iOSアプリでのローカルDNSサーバーのDNS解決期間と解決結果の取得

最終更新日:Nov 12, 2024

このトピックでは、iOSアプリでネットワークリクエストを実行するときに、ドメインネームシステム (DNS) 解決期間とローカルDNSサーバーの解決結果を取得する方法について説明します。

1. 概要

NSURLSessionDelegateプロトコルで定義されたメソッドを使用して、iOSアプリでネットワークリクエストを実行するときにローカルDNSサーバーの解決期間を取得できます。 Alibaba Cloud Public DNS SDKをiOSアプリと統合すると、ローカルDNSサーバーではなくSDKがDNS解決を実行します。 この場合、SDKが使用するAPI操作で実行されるDNS解決の開始時刻と終了時刻の間の時間範囲を計算することで、DNS解決期間を取得できます。

getaddrinfoをiOSアプリと統合して、ローカルDNSサーバーの解決結果を取得できます。 これにより、ドメイン名のハイジャックが発生したかどうかを判断できます。

2. ソリューション

  • HTTP APIがhttps:// domain/pathで表されている場合、次のセクションのコードでは、DNSサーバーの解決期間を取得する方法の例を示します。

  • 説明

    iOS 14でネイティブの暗号化されたDNSを使用してDNSサーバーを設定する場合、次のコードを実行して、設定されたDNSサーバーの解決期間を取得できます。 それ以外の場合は、ローカルDNSサーバーの解決期間を取得します。

#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:@"Request URL:%@",[obj.request.URL absoluteString]]);
            NSLog(@"%@",[NSString stringWithFormat:@"Server IP address:%@",obj.remoteAddress]);

            NSURLSessionTaskMetricsDomainResolutionProtocol dnsProtocol = obj.domainResolutionProtocol;
            NSLog(@"%@",[NSString stringWithFormat:@"The protocol for DNS resolution is %ld", (long)dnsProtocol]);
            NSLog(@"%@",[NSString stringWithFormat:@"0:Unknown, 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 resolution start time:%@,DNS resolution end time:%@", obj.domainLookupStartDate, obj.domainLookupEndDate]);
                NSLog(@"%@",[NSString stringWithFormat:@"DNS resolution duration Unit ms:%d",dnsLookupTime]);
            }
        }
    }];
}
  • Alibaba Cloud Public DNS SDKをiOSアプリと統合すると、次のコードを実行して、Alibaba Cloud Public DNS SDKのDNS解決期間を取得できます。

CFTimeInterval startTimer = CACurrentMediaTime();
// Replace the value with the SDK DNS resolution method that you use.
[[DNSResolver share] getIpv4DataWithDomain:@"main.m.taobao.com" complete:^(NSArray<NSString *> *dataArray) {
    CFTimeInterval endTimer = CACurrentMediaTime();
    UInt32 rtt = (endTimer - startTimer) * 1000;
    NSLog(@"%@",[NSString stringWithFormat:@"DNS resolution Unit ms:%d",rtt]);                   
}];

3. ローカルDNSサーバーの解決結果を取得し、ドメイン名ハイジャックが発生するかどうかを判断します

次のコードを使用して、ローカルDNSサーバーの解決結果を取得できます。 これにより、取得した結果と予想される結果を比較して、ドメイン名のハイジャックが発生したかどうかを判断できます。

#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));

    // Initialize hints structure
    hints.ai_family = AF_UNSPEC; // IPv4 or IPv6
    hints.ai_socktype = SOCK_STREAM; // TCP
    
    // Perform DNS query
    int s = getaddrinfo([domain UTF8String], NULL, &hints, &result);
    if (s != 0) {
        NSLog(@"getaddrinfo error: %s", gai_strerror(s));
        return;
    }

    BOOL isHijacked = NO;

    // Traverse the result to obtain IPv4 and IPv6 addresses
    for (p = result; p != NULL; p = p->ai_next) {
        char ipBuffer[INET6_ADDRSTRLEN]; // Buffer zone is used to format IP address
        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 address: %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 address: %s", ipBuffer);
        }

        // Compare the obtained results with the expected results
        if (![expectedIPs containsObject:[NSString stringWithUTF8String:ipBuffer]]) {
            isHijacked = YES;
        }
    }

    // Determine if hijacking occurs
    if (isHijacked) {
        NSLog(@"Warning: DNS may be hijacked!");
    } else {
        NSLog(@"No DNS hijacking is detected.");
    }

    // Release memory
    freeaddrinfo(result);
}