iOS HttpDNS实践

项目中用到了HTTPDNS,顺便把做的过程和遇到的流程记录下。

1、为啥要做HttpDNS?

对于互联网,域名是访问的第一跳,而这一跳很多时候会“失足”,导致访问错误内容,失败连接等。
HttpDNS是使用HTTP协议向DNS服务器的80端口进行请求,代替传统的DNS协议向DNS服务器的53端口进行请求,绕开了运营商的Local DNS,从而避免了使用运营商Local DNS造成的劫持和跨网问题。具体可以看看鹅厂的这篇文章( 鹅厂DNS分析 ).

2、怎么做的?

我这边选用的腾讯云的移动解析HttpDNS,接入SDK,SDK链接。注意在配置的时候要在info.plist配置Demo中给出的信息,等公司申请下来账号以后替换对应的key和id。

/**
 域名解析ip
 @param host 域名
 @return ip(优先使用ipv6),没解析到返回host
 */    
- (NSString *)dnsByDomain:(NSString *)domain {
    NSTimeInterval time1 = [[NSDate date] timeIntervalSince1970];
    NSArray *result = [[MSDKDns sharedInstance] WGGetHostByName:domain];
    NSTimeInterval time2 = [[NSDate date] timeIntervalSince1970];
    NSLog(@"HttpDNS 本次耗时:%f", (time2 - time1) * 1000);
    if (result && result.count > 1) {
        NSString *ipv4 = result[0];
        NSString *ipv6 = result[1];
        if (ipv6 && ipv6.length > 1) {
            NSLog(@"HttpDNS domain(%@),ip(%@)", domain, ipv6);
            return [NSString stringWithFormat:@"%@", ipv6];
        } else if (ipv4 && ipv4.length > 1) {
            NSLog(@"HttpDNS domain(%@),ip(%@)", domain, ipv4);
            return [NSString stringWithFormat:@"%@", ipv4];
    }
}

return nil;
}

其中比较重要的是如何拦截网络请求,把其中的域名换成对应的ip地址。

我在项目中,选用的是自定义NSURLProtocol的方法,对于不了解的同学可以在这个地方科普下 NSURLProtocol 科普

3、遇到的问题

在前面两步做的都比较顺利,在把域名替换成ip访问网络的时候出现的问题:“返回此服务器的证书无效。您可能正在连接到一个伪装成“14.215.177.37”的服务器,这会威胁到您的机密信息的安全(14.215.177.37 是www.baidu.com的ip)。”
后来自信看了sdk文档,发现在Https建立连接的时候是需要验证证书的, Https场景处理

但是按照文档方法写了后还是不能访问,

/*
 * 评估当前serverTrust是否可信任,
 * 官方建议在result = kSecTrustResultUnspecified 或 kSecTrustResultProceed
 * 的情况下serverTrust可以被验证通过,https://developer.apple.com/library/ios/technotes/tn2232/_index.html
 * 关于SecTrustResultType的详细信息请参考SecTrust.h
 */
SecTrustResultType result;
SecTrustEvaluate(serverTrust, &result);

return (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);

后来看了返回的错误信息,发现加上result == kSecTrustResultRecoverableTrustFailure就可以正常处理了。

关于证书信任
用户是否是自己主动设置信任的,比如有些弹窗,用户点击了信任
1.用户自定义的,成功是 kSecTrustResultProceed 失败是kSecTrustResultDeny
2.非用户定义的, 成功是kSecTrustResultUnspecified 失败是kSecTrustResultRecoverableTrustFailure
这个感觉是服务器的问题,还没有确定问题原因。
Https建立连接过程

你可能感兴趣的:(iOS HttpDNS实践)