iOS下使用HttpDNS进行IP直连避免DNS劫持

如题所述

第1个回答  2022-06-14
IP直连可以避免localDNS解析导致的DNS劫持,但是在iOS中不仅仅是将host直接换成IP地址就可以了,还有以下需要注意的问题。

发送HTTPS请求首先要进行SSL/TLS握手,握手过程大致如下:

上述过程中,和HTTPDNS有关的是第3步,客户端需要验证服务端下发的证书,验证过程有以下两个要点:

如果上述两点都校验通过,就证明当前的服务端是可信任的,否则就是不可信任,应当中断当前连接。 当客户端使用HTTPDNS解析域名时,请求URL中的host会被替换成HTTPDNS解析出来的IP,所以在证书验证的第2步,会出现domain不匹配的情况,导致SSL/TLS握手不成功 。

针对 domain不匹配 问题,可以采用如下方案解决:hook证书校验过程中第2步,将IP直接替换成原来的域名,再执行证书验证。

方法为在客户端收到服务器的质询请求代理方法 -URLSession:task:didReceiveChallenge:completionHandler: 中,首先从header中获取host(第一点注意事项:HTTP请求头HOST字段设置),从header中如果没有取到host,就去URL中获取host(降级为LocalDNS解析时不进行替换),然后拿着host在自己的方法-evaluateServerTrust:forDomain:中创建SSL Policy证书校验策略,然后对证书进行校验。

SNI(Server Name Indication)是为了解决一个服务器使用多个域名和证书的SSL/TLS扩展。它的工作原理如下:
在连接到服务器建立SSL链接之前先发送要访问站点的域名(Hostname),服务器根据这个域名返回一个合适的证书。
目前,大多数操作系统和浏览器都已经很好地支持SNI扩展,OpenSSL 0.9.8也已经内置这一功能。
上述过程中,当客户端使用HTTPDNS解析域名时,请求URL中的host会被替换成HttpDNS解析出来的IP,导致SSL/TLS握手中服务器接收到的客户端发出的clientHello中的SNI为host解析后的IP,从而无法找到匹配的证书,只能返回默认的证书或者不返回,所以会出现SSL/TLS握手不成功的错误。

比如当你需要通过HTTPS访问CDN资源时,CDN的站点往往服务了很多的域名,所以需要通过SNI指定具体的域名证书进行通信。

SNI(单IP多HTTPS证书)场景下,iOS上层网络库 NSURLConnection/NSURLSession 没有提供接口进行 SNI 字段 配置,因此需要 Socket 层级的底层网络库例如 CFNetwork,来实现 IP 直连网络请求适配方案。苹果提供的一些指导,在 Networking Programming Topics 中,可以通过如下方式指定一个TLS hostname:

我们使用CFNetwork进行HTTP网络请求的方法,详见 [2] 。

Apple - Communicating with HTTP Servers
Apple - HTTPS Server Trust Evaluation - Server Name Failures
Apple - HTTPS Server Trust Evaluation - Trusting One Specific Certificate

[1]:HTTPS场景IP直连方案说明
[2]:使用CFNetwork进行HTTP请求

相关了解……

你可能感兴趣的内容

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 非常风气网