术→技巧, 运维

移动域名解析HTTPDNS

钱魏Way · · 397 次浏览

HTTPDNS简介

传统域名解析面临的诸多问题与挑战本质根源在于 Local DNS 的服务质量不可控,如果有一个更安全、稳定、高效的递归 DNS 服务帮助我们代理了域名解析的过程,这些问题就可以彻底地得到解决。

HTTPDNS 在这样的背景下应运而生。我们一起来看看 HTTPDNS 的基本概念以及它是如何解决传统 DNS 解析面临的问题的。

运营商劫持

DNS劫持 就是通过劫持了 DNS 服务器,通过某些手段取得某域名的解析记录控制权,进而修改此域名的解析结果,导致对该域名的访问由原 IP 地址转入到修改后的指定 IP,其结果就是对特定的网址不能访问或访问的是假网址,从而实现窃取资料或者破坏原有正常服务的目的。

HTTPDNS 使用 HTTP 协议进行域名解析,代替现有基于 UDP 的 DNS 协议,域名解析请求直接发送到 HTTPDNS 服务端,从而绕过运营商的 Local DNS。

HTTPDNS 代替了传统的 LocalDNS 完成递归解析的功能,基于 HTTP 协议的设计可以适用于几乎所有的网络环境,同时保留了鉴权、HTTPS 等更高安全性的扩展能力,避免恶意攻击劫持行为。另一方面,商业化的 HTTPDNS 服务(比如阿里云 HTTPDNS、腾讯云 HTTPDNS)缓存管理有严格的 SLA 保障,避免了类似 Local DNS 的缓存污染的问题。

域名缓存

LocalDNS缓存了域名的解析结果,不向权威DNS发起递归。

LocalDNS要把域名解析结果进行原因有以下几个:

  • 保证用户访问流量在本网内消化:国内的各互联网接入运营商的带宽资源、网间结算费用、IDC机房分布、网内ICP资源分布等存在较大差异。为了保证网内用户的访问质量,同时减少跨网结算,运营商在网内搭建了内容缓存服务器,通过把域名强行指向内容缓存服务器的IP地址,就实现了把本地本网流量完全留在了本地的目的。
  • 推送广告:有部分LocalDNS会把部分域名解析结果的所指向的内容缓存,并替换成第三方广告联盟的广告。

这种类型的行为就是我们常说的域名缓存,域名缓存会导致用户产生以下的访问异常:

  • 仅对80端口的http服务做了缓存,如果域名是通过https协议或其它端口提供服务的,用户访问就会出现失败。比如支付服务、游戏通过指定端口连接connect server服务等。
  • 缓存服务器的运维水平参差不齐,时有出现缓存服务器故障导致用户访问异常的问题。

在域名解析生效周期方面,HTTPDNS 也有着传统域名解析体系所无法具备的能力。前面我们提到由于各个地区的 Local DNS 是独立维护的,服务质量参差不齐,缓存实现不一,因此导致的解析变更全网生效滞后的问题,在商业化的 HTTPDNS 服务上就不会存在(HTTPDNS 严格遵循 DNS TTL 限制进行缓存更新)。另一方面,即便我们假设 Local DNS 严格遵循域名 TTL 时间进行缓存管理(这里我们假设运维配置的域名 TTL 时间为 5min),当我们的业务受到攻击并需要快速进行切换时,Local DNS 也会遵循域名 TTL,在持续 5min 的时间段内返回旧 IP 信息,这 5min 的业务影响对于中大型企业而言是一个不小的损失(对于电商类的大型企业,5min 的访问异常可能意味着几百万的交易额下跌)。以阿里云 HTTPDNS 服务,HTTPDNS 在快速生效方面有专有的方案,配合阿里云的权威 DNS 服务云解析(我们的域名都是部署在阿里云的权威 DNS 服务云解析上面),用户在权威 DNS 变更的解析结果将快速同步给 HTTPDNS,覆盖原有的缓存记录,帮助用户实现毫秒级的域名解析切换。

解析转发:

除了域名缓存以外,运营商的LocalDNS还存在解析转发的现象。解析转发是指运营商自身不进行域名递归解析,而是把域名解析请求转发到其它运营商的递归DNS上的行为。正常的LocalDNS递归解析过程是这样的:

而部分小运营商为了节省资源,就直接将解析请求转发到了其它运营的递归LocalDNS上去了:

这样的直接后果就是权威DNS收到的域名解析请求的来源IP就成了其它运营商的IP,最终导致用户流量被导向了错误的IDC,用户访问变慢。

LocalDNS递归出口NAT

LocalDNS递归出口NAT指的是运营商的LocalDNS按照标准的DNS协议进行递归,但是因为在网络上存在多出口且配置了目标路由NAT,结果导致LocalDNS最终进行递归解析的时候的出口IP就有概率不为本网的IP地址:

这样的直接后果就是GSLB DNS收到的域名解析请求的来源IP还是成了其它运营商的IP,最终导致用户流量被导向了错误的IDC,用户访问变慢。

解析生效滞后

部分业务场景下开发者对域名解析结果变更的生效时间非常敏感(这部分变更操作是开发者在权威DNS上完成的),比如当业务服务器受到攻击时,我们需要最快速地将业务IP切换到另一组集群上,这样的诉求在传统域名解析体系下是无法完成的。

Local DNS的部署是由各个地区的各个运营商独立部署的,因此各个Local DNS的服务质量参差不齐。在对域名解析缓存的处理上,各个独立节点的实现策略也有区别,比如部分节点为了节省开支忽略了域名解析结果的TTL时间限制,导致用户在权威DNS变更的解析结果全网生效的周期非常漫长(我们已知的最长生效时间甚至高达48小时)。这类延迟生效可能直接导致用户业务访问的异常。

商业化的 HTTPDNS 服务,都具备 99.99% 的高可用性, 确保域名解析服务稳定可靠。

HTTPDNS 客户端直接通过 IP 来进行域名解析请求的,HTTPDNS  SDK 内部维护一个 IP 轮询池,当某个 IP 不可用时,会自动切换其他的 IP,并且 IP 轮询池也会更新。

HTTPDNS 服务端方面,拿阿里云的 HTTPDNS 来说,在全球有数十个服务集群,各个服务集群互相备份,具备异地容灾备份功能,当某个服务集群不可用时,会自动切换到其他的服务集群,可以确保解析和缓存正常。

HTTPDNS原理

HttpDNS的原理非常简单,主要有两步:

  • 客户端直接访问HttpDNS接口,获取业务在域名配置管理系统上配置的访问延迟最优的IP。(基于容灾考虑,还是保留次选使用运营商LocalDNS解析域名的方式)
  • 客户端向获取到的IP后就向直接往此IP发送业务协议请求。以Http请求为例,通过在header中指定host字段,向HttpDNS返回的IP发送标准的Http请求即可。

HttpDNS优势

从原理上来讲,HttpDNS只是将域名解析的协议由DNS协议换成了Http协议,并不复杂。但是这一微小的转换,却带来了无数的收益:

  • 根治域名解析异常:由于绕过了运营商的LocalDNS,用户解析域名的请求通过Http协议直接透传到了HttpDNS服务器IP上,用户在客户端的域名解析请求将不会遭受到域名解析异常的困扰。
  • 调度精准:HttpDNS能直接获取到用户IP,通过结合腾讯自有专利技术生成的IP地址库以及测速系统,可以保证将用户引导的访问最快的IDC节点上。
  • 实现成本低廉:接入HttpDNS的业务仅需要对客户端接入层做少量改造,无需用户手机进行root或越狱;而且由于Http协议请求构造非常简单,兼容各版本的移动操作系统更不成问题;另外HttpDNS的后端配置完全复用现有权威DNS配置,管理成本也非常低。总而言之,就是以最小的改造成本,解决了业务遭受域名解析异常的问题,并满足业务精确流量调度的需求。
  • 扩展性强:HttpDNS提供可靠的域名解析服务,业务可将自有调度逻辑与HttpDNS返回结果结合,实现更精细化的流量调度。比如指定版本的客户端连接请求的IP地址,指定网络类型的用户连接指定的IP地址等。
  • 用户连接失败率下降:通过算法降低以往失败率过高的服务器排序,通过时间近期访问过的数据提高服务器排序,通过历史访问成功记录提高服务器排序。
  • 平均访问延迟下降:由于是 IP 直接访问省掉了一次 domain 解析过程,通过智能算法排序后找到最快节点进行访问。

HTTPDNS搭建

HTTPDNS设计中关键点

  • 安全策略:HTTPDNS查询是基于标准的HTTP协议,但是如果为了保证安全,可以使用HTTPS;
  • IP选取策略:HTTPDNS服务将最优IP按照顺序下发,客户端默认选取第一个,校验连通性OK就使用,如果不OK,选用下一个校验;
  • 缓存过期策略:后端动态下发域名的TTL时间,当域名的TTL超时后,如果没有新的IP将继续沿用老的IP,也可以降级成Local DNS返回的IP。
  • 批量拉取策略:在应用冷启动 或 网络切换时候,批量拉取域名和IP列表的映射数据,缓存下来;以便在后续请求中使用到,预期提升精准调度能力。
  • 降级策略:当HTTPDNS服务不可用 & 本地也没有缓存或者缓存失效时,降级成运营商的Local DNS方案;当HTTPDNS服务 & Local DNS服务双双不可用的情况下,可以使用BACKUP IP;

HTTPDNS最佳实践

移动APP的域名解析机制,新的流程参考如下:

需要注意的是,发起网络请求时,在本地无缓存,或缓存已过期的情况下,直接使用localDNS解析,并同时异步更新本地DNS缓存。

Failed over策略降级

虽然HttpDNS已经接入BGP Anycast,并实现了多地跨机房容灾。但为了保证在最坏的情况下客户端域名解析依然不受影响。建议采用以下的fail over策略:

  • 第一步先向HttpDNS发起域名查询请求
  • 如果HttpDNS查询返回的结果不是一个IP地址(结果为空、结果非IP、连接超时等),则通过本地 LocalDNS进行域名解析。超时时间建议为5s。

不管是因为什么原因,当通过HTTPDNS服务无法获得域名对应的IP时,都必须降级:使用标准的DNS解析,通过Local DNS去解析域名。

缓存策略

移动互联网用户的网络环境比较复杂,为了尽可能地减少由于域名解析导致的延迟,建议在本地进行缓存。缓存规则如下:

  • 缓存时间。缓存时间建议设置为120s至600s,不可低于60s。
  • 缓存更新。缓存更新应在以下两种情形下进行:
    • 用户网络状态发生变化时: 移动互联网的用户的网络状态由3G切Wi-Fi,Wi-Fi切3G的情况下,其接入点的网络归属可能发生变化。所以用户的网络状态发生变化时,需要重新向HttpDNS发起域名解析请求,以获得用户当前网络归属下的最优指向。
    • 缓存过期时:当域名解析的结果缓存时间到期时,客户端应该向HttpDNS重新发起域名解析请求以获取最新的域名对应的IP。为了减少用户在缓存过期后重新进行域名解析时的等待时间,建议在75%TTL时就开始进行域名解析。如本地缓存的TTL为600s,那么在第600*0.75=450s时刻,客户端就应该进行域名解析。

除了以上几点建议外,减少域名解析的次数也能有效的减少网络交互,提升用户访问体验。建议在业务允许的情况下,尽量减少域名的数量。如需区分不同的资源,建议通过url来进行区分。

异步请求、懒加载

异步请求策略:解析域名时,如果当前缓存中有TTL未过期的IP,可直接使用;如果没有,则立刻让此次请求降级走原生LocalDNS解析,同时另起线程异步地发起HTTPDNS请求进行解析,更新缓存,这样后续解析域名时就能命中缓存。

  • 查询注册的DNS解析列表,若未注册返回null
  • 查询缓存,若存在且未过期则返回结果,若不存在返回null并且进行异步域名解析更新缓存。
  • 若接口返回null,降级到local dns解析策略。

懒加载策略的实施可以让我们真正实现 DNS 的零延迟解析。所谓懒加载策略,核心的实现思路如下:

  • 业务层的域名解析请求只和缓存进行交互,不实际发生网络解析请求。如果缓存中存在记录,不论过期与否,直接返回业务层缓存中的记录;
  • 如果缓存中的记录已过期,后台发起异步网络请求进行 HTTPDNS 解析;

下图描绘了预解析+懒加载的实现框架:

重试

访问HTTPDNS服务解析域名时,如果请求HTTPDNS服务端失败,即HTTP请求没有返回,可以进行重试。 大部分情况下,这种访问失败是由于网络原因引起的,重试可以解决。

预解析

绝大多数的 APP 在应用初始化阶段都有一个启动期,我们可以在这个启动期做一些 preflight 工作,即在初始化阶段我们可以针对业务的热点域名在后台发起异步的 HTTPDNS 解析请求。这部分预解析结果在后续的业务请求中可以直接使用,进而消除首次业务请求的 DNS 解析开销,提升 APP 首页的加载速度。

HTTPS

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

  • 客户端发起握手请求,携带随机数、支持算法列表等参数。
  • 服务端收到请求,选择合适的算法,下发公钥证书和随机数。
  • 客户端对服务端证书进行校验,并发送随机数信息,该信息使用公钥加密。
  • 服务端通过私钥获取随机数信息。
  • 双方根据以上交互的信息生成session ticket,用作该连接后续数据传输的加密密钥。

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

  • 客户端用本地保存的根证书解开证书链,确认服务端下发的证书是由可信任的机构颁发的。
  • 客户端需要检查证书的domain域和扩展域,看是否包含本次请求的host。

如果上述两点都校验通过,就证明当前的服务端是可信任的,否则就是不可信任,应当中断当前连接。

当客户端使用HTTPDNS解析域名时,请求URL中的host会被替换成HTTPDNS解析出来的IP,所以在证书验证的第2步,会出现domain不匹配的情况,导致SSL/TLS握手不成功。

webview

Flutter

OkHttp

代理情况

当存在中间HTTP代理时,客户端发起的请求中请求行会使用绝对路径的URL,在开启HTTPDNS并采用IP URL进行访问时,中间代理将识别您的IP信息并将其作为真实访问的HOST信息传递给目标服务器,这时目标服务器将无法处理这类无真实HOST信息的HTTP请求。

绝大多数场景下,在代理模式下关闭HTTPDNS功能。

注意事项

  • 设置的缓存TTL值不可太低(不可低于60s),防止频繁进行HtppDNS请求。
  • 接入HttpDNS的业务需要保留用户本地LocalDNS作为容灾通道,当HttpDNS无法正常服务时(移动网络不稳定或HttpDNS服务出现问题),可以使用LocalDNS进行解析。
  • https问题,需在客户端hook客户端检查证书的domain域和扩展域看是否包含本次请求的host的过程,将IP直接替换成原来的域名,再执行证书验证。或者忽略证书认证,类似于curl -k参数。
  • HttpDNS请求建议超时时间2-5s左右。
  • 在网络类型变化时,如4G切换到wifi,不同wifi间切换等,需要重新执行HttpDNS请求刷新本地缓存。

参考链接:

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注