DNS是域名系统(DomainNameSystem)的缩写,该系统用于命名组织到域层次结构中的计算机和网络服务。域名是由圆点分开一串单词或缩写组成的,每个域名都对应一个唯一的IP地址,在Internet上域名与IP地址之间是一一对应的,DNS就是进行域名解析的服务器。DNS命名用于Internet等TCP/IP网络中,经过用户友好的名称查找计算机和服务。DNS是因特网的一项核心服务,它做为能够将域名和IP地址相互映射的一个分布式数据库。前端
当咱们发起一个网络请求,首先要通过DNS服务,将域名转化为IP地址,而后经过IP地址创建链接。DNS的工做流程以下图所示。java
那么,传统的Local DNS有什么缺陷呢。就目前端上而言,主要有几个问题:android
域名劫持是互联网攻击的一种方式,经过攻击域名解析服务器(DNS),或伪造域名解析服务器(DNS)的方法,把目标网站域名解析到错误的地址从而实现用户没法访问目标网站的目的。git
DNS劫持示例图以下:github
DNS劫持会致使端上网络链接失败或者DNS解析失败,严重影响用户使用,在以前,端上采用备用域名的机制去解决这个问题,可是效果并非很好。数据库
DNS解析分为递归查询和迭代查询两种。缓存
递归查询:若是主机所询问的本地域名服务器不知道被查询域名的 IP 地址,那么本地域名服务器就以 DNS 客户的身份,向其余根域名服务器继续发出查询请求报文,而不是让该主机本身进行下一步的查询。安全
迭代查询:当根域名服务器收到本地域名服务器发出的迭代查询请求报文时,要么给出所要查询的 IP 地址,要么告诉本地域名服务器:你下一步应当向哪个域名服务器进行查询。而后让本地域名服务器进行后续的查询,而不是替本地域名服务器进行后续的查询。服务器
因为递归模式会致使DNS服务器流量很大,因此如今大多数采用迭代模式。微信
因为端上网络环境的复杂性已经DNS解析的流程也较为复杂,有些场景下DNS解析时间高达几百毫秒,对于一次网络请求来讲,是至关缓慢的。
HTTPDNS 是面向移动开发者推出的一款域名解析产品,具备域名防劫持、精准调度等特性。
目前来讲,腾讯和阿里都有本身的HTTPDNS解决方案。HTTPDNS有如下特性:
在阿里云HTTPDNS文档中,有所谓的“最佳方案”,包含SNI场景、OkHttp场景等等,可是,这对于咱们来讲,接入量仍是偏大,且覆盖的场景依然有限。若是咱们想很简单的接入,且覆盖全量Java场景,如何作呢。首先,咱们看一下Android侧DNS解析的调用流程,以API 28为例。
InetAddress#getAllByName()
->Inet6AddressImpl#lookupHostByName()
->Libcore.os.android_getaddrinfo()
复制代码
而Libcore代码以下Libcore源码:
public final class Libcore {
private Libcore() { }
/** * Direct access to syscalls. Code should strongly prefer using {@link #os} * unless it has a strong reason to bypass the helpful checks/guards that it * provides. */
public static Os rawOs = new Linux();
/** * Access to syscalls with helpful checks/guards. */
public static Os os = new BlockGuardOs(rawOs);
}
复制代码
经过简单的代码跟踪能够发现,他们实现Os这个接口 ,接口?对哦,动态代理。是的,咱们能够经过动态代理的方式,去hook掉Java层发起的DNS解析请求。
上面的代码,已经开源在KIDDNS-Android
Android P hide API的问题相信困扰了很多同窗,那么下期,我们一块儿了解下如何在Android P上使用hide API!
欢迎你们关注个人我的微信公众号《Andorid小茶馆》!主要内容是移动端,主要是Android方向,技术交流,开源分析,架构浅谈。