图片起源:https://unsplash.com/photos/Q…
作者:念山
背景
随着技术的倒退,网络环境也变得越来越简单,而对于一个以网络数据传输提供服务的 App 来讲,在复杂多变的网络环境下平安稳固无效的提供好服务显得尤为重要。而为了提供平安稳固无效的 HTTP 网络服务,咱们从网络申请的初始阶段 DNS 解析上保障 DNS 安全性的技术:去剖析下苹果 2022 年 WWDC 讲到的 DNSSEC 技术和咱们云音乐现行的 HTTPDNS 并做下比照。
什么是 DNS
域名零碎(Domain Name System,DNS)则是将域名解析 IP 地址的一项互联网根底服务,提供该服务的服务器称为 域名服务器(Domain Name Server)。
域名(Domain Name,Domain)是一个在互联网上标识主机或主机组的名称,相当于 IP 地址的别名,绝对于艰涩难记的 IP 地址,域名更显得易于记忆。
域名零碎是怎么工作的呢
互联网上的域名零碎是一个分布式的零碎,构造上是一个四层的树状层次结构:
- 本地域名服务器(Local Name Server,local DNS):如果通过 DHCP 配置,local DNS 由互联网服务提供商(ISP,如联通、电信)提供
- 根域名服务器(Root Name Server):当 local DNS 查问不到解析后果时,第一步会向它进行查问,并获取顶级域名服务器的 IP 地址。寰球一共有 13 个根域名服务器(除了它们的镜像),它们并不间接用于域名解析,仅用于指出可查问的顶级域名服务器。
- 顶级域名服务器(Top-level Name Server):负责管理在该顶级域名服务器下注册的二级域名,例如.com 顶级域名服务器,而 baidu.com 权威服务器是注册在 .com 的权威域名服务器
- 权威域名服务器(Authoritative Name Server):在特定区域内具备唯一性,负责保护该区域内的域名与 IP 地址的映射关系。在 DNS 应答报文中,标记位 AA 标识本次 DNS 记录是否来自权威域名服务器,否则可能来自缓存
模仿流程
那以咱们主站域名 interface.music.163.com 为例,来看一下 DNS 的过程:
- 0、首先查看 DNS 缓存,如果缓存老化或未命中,客户端须要向 local DNS 发送查问申请报文
- 1、客户端向 local DNS 发送查问报文 query interface.music.163.com,local DNS 首先查看本身缓存,如果存在记录则间接返回后果,查问完结;如果缓存老化或未命中,则:
- 2、local DNS 向根域名服务器发送查问报文 query interface.music.163.com,返回 .com 顶级域名服务器的地址(如果查无记录)
- 3、local DNS 向 .com 顶级域名服务器发送查问报文 query interface.music.163.com,返回 interface.music.163.com 所在的权威域名服务器的地址(如果查无记录)
- 4、local DNS 向 interface.music.163.com 权威域名服务器发送查问报文 query interface.music.163.com,失去 ip 地址,存入本身缓存并返回给客户端
DNS 特点
DNS 从 1983 年设计推出到当初曾经在寰球运作 40 年了,设施反对高,然而因为最后设计的时候没有思考平安相干的问题,报文无鉴权和加密相干的信息,带来了不稳固的因素。
劣势
- 零碎反对
- 速度快
劣势
-
中间人攻打
- DNS 坑骗
- DNS 劫持
- 结构复杂,两头变数多
针对 DNS 不平安的状况,业界也在通过 DNSSEC、HTTPDNS 等技术计划补充来去保障平安进步服务可用。
什么是 DNSSEC
DNSSEC 能够说是在原有 DNS 根底之上做的扩大。
网域名称零碎安全性裁减 (DNSSEC) 可为网域名称的 DNS (网域名称零碎) 加上电子签名,藉此判断起源网路名称的真实性。此性能能够爱护网路使用者不受编造 DNS 材料的威逼,让使用者要求正确网址时不会获得其余无意误导或歹意制作的网址。
DNSSEC 工作的流程
DNSSEC 通过建设信赖链来验证记录
举个例子:设施想要解析 www.example.org 并启用 DNSSEC 验证,过程如下:
- 发送询问 IP 地址、签名和密钥的查问,通过响应能够建设从 IP 地址到密钥 1 的信赖关系
- 客户端向父区域 org 发送查问,询问可用于验证密钥 1 的记录,建设从密钥 1 到密钥 2 的信赖关系
- 设施递归地反复这个过程,直到它达到根域
DNSSEC 特点
通过流程总结下来
劣势
-
提供校验保障平安
劣势
-
须要路由器反对,路由器必须反对解决大于失常大小的 DNS 包
- 失常的 DNS 包大小为 512 字节,DNSSEC 则大于 512 字节,国内较多路由器会抛弃超过 512 字节的 DNS 包
- 域名注册服务商配置大部分是付费的
-
云商反对弱
- 较多云商不反对 DNSSEC 解析
- 反对 DNSSEC 解析的根本还免费
- 须要权威服务器反对
-
零碎兼容差
- iOS16+ 反对
- macOS Ventura 以上才反对
是否要抉择 DNSSEC?
DNSSEC 计划对于咱们 App 来讲不可控因素太多,且可扩展性较弱所以咱们抉择了一套同样平安,且更为可控的计划 – HTTPDNS。
HTTPDNS
相较于 DN S 和 DNSSEC,对于客户端来讲有一种可控性更强和更平安的计划:HTTPDNS,而 HTTPDNS 也是咱们云音乐当初正在运行的计划。
什么是 HTTPDNS
DNSOverHTTP,通过 HTTP 报文申请来去拉取 DNS 的后果,客户端拿到后果后拿 IP 替换申请的 host 并设置 SNI 来去进行 IP 直连的申请,达到管制申请目标 IP 抉择的后果,达到等同 DNS 的性能。
HTTPDNS 流程
- 客户端申请本人 HTTPDNS 服务器拿到 IP
- 发申请替换 host 为对应的 IP
- 设置 SNI 来增加原始 host 信息
HTTPDNS 特点
劣势
- 可定制化强 : 服务走本人服务器
- 平安 : 走 https 申请
劣势
- 相较于 LocalDNS 工夫损耗长:因为采纳 HTTP 报文来去传输 domain 与 IP 的映射表
- 须要本人解决替换域名的操作。
- 具备肯定的平安危险:iPhone 须要调用公有 API 去设置 SNI
平安危险
一个比拟大的危险点是在应用公有 API 来去设置 SNI。
在基于目前网络根本应用 NSURLSession 的大背景下,在应用 HTTPDNS 技术的状况下有个重要的一个过程是通过公有 API 来设置 SNI 信息通过 HTTPS 的握手校验。然而公有 API 有随时被封禁的危险,如若被封禁则应用公有 API 来做 SNI 设置的 HTTPS 申请都不可用。
怎么来躲避应用公有 API 这个平安危险呢?
外围问题
NSURLSession 无法控制 Socket 连贯,所以只能替换 host 的形式来去解决,如果通过管制 Socket 连接池,就能躲避掉 SNI 的问题
新的网络库
咱们抉择一套新的网络库 Cronet 既能管制 Socket 连接池,又能带来网络性能相干的晋升及网络高级个性的反对。
IP 跑马
HTTPDNS 拿到的是一个 IP 数组,理论发申请的时候只须要一个 IP,那到底应用哪个 IP 来进行建连申请呢?那就须要通过肯定的计分规范来给 IP 打分,通过 IP 跑马来拿到最佳 IP。
计分规定
单次申请的评分
单次申请评分依照正确申请和谬误申请两种不同的计分形式来进行解决。
谬误评分
把网络谬误细分为 5 个等级,不同等级扣分分值不一样
typedef NS_ENUM(NSInteger, NENetErrorLevel)
{
NENetErrorLevelNone, // 无谬误,不扣分
NENetErrorLevelDefault, // 默认,扣 1 分
NENetErrorLevelisCancel, // 勾销不算谬误,不扣分
NENetErrorLevelNormal, // 一般级别 扣 10 分
NENetErrorLevelSerious, // 重大 扣 20 分
};
// 把对应的 NSURLSession 的网络报错对应到谬误等级进行评分
- (NENetErrorLevel)errorLevelForError:(NSError *)error
{
NENetErrorLevel errorLevel =NENetErrorLevelNone;
BOOL isCancel = NO;
BOOL isChainError = NO;
BOOL isTimeout = NO;
NSError *urlError = error;
NSInteger errorCode = urlError.code;
if ([urlError.domain isEqualToString:NSURLErrorDomain] ||
[urlError.domain isEqualToString:@"AFNetworkingErrorDomain"])
{if (errorCode == NSURLErrorCannotConnectToHost)
{isChainError = YES;}
isTimeout = errorCode == NSURLErrorTimedOut;
isCancel = errorCode == NSURLErrorCancelled;
}
else if ([urlError.domain isEqualToString:NSPOSIXErrorDomain])
{
if (errorCode == 54 || //ECONNRESET
errorCode == 57 || //ENOTCONN
errorCode == 60 || //ETIMEDOUT
errorCode == 61 ||
errorCode == 65
) //ECONNREFUSED
{isChainError = YES;}
}
if (isCancel) {errorLevel = NENetErrorLevelisCancel;} else if (isChainError) {errorLevel = NENetErrorLevelSerious;} else if (isTimeout) {errorLevel = NENetErrorLevelNormal;} else if (error) {errorLevel = NENetErrorLevelDefault;}
return errorLevel;
}
正确的评分
正确的评分采纳申请速度来去考量分值,抉择基准线速度和工夫,在基准线上线浮动进行算分。
耗时 <=2.5s 才会去依照基准线进行计算分
耗时 >4.5s 开始扣分
// 计算公式
- (double)calcllateSuccessMarkWithDataLength:(NSUInteger)dataLength cost:(NSTimeInterval)cost
{if (cost == 0) {return 0;}
double mark;
long delta = 0;
if (cost <= CALL_TIME_GOOD_BENCH_MARK) { // 如果 <= 2.25s,才有积分机会
delta = CALL_TIME_GOOD_BENCH_MARK - cost;
} else if (cost > CALL_TIME_BAD_BENCH_MARK) { // 如果 > 4.5s, 则开始扣分
delta = CALL_TIME_BAD_BENCH_MARK - cost;
}
// 超时不肯定是 IP 有问题
// 通过耗时维度计算出的 mark 最低 - 5 分
mark = MAX(delta,-5);
if (dataLength > 0 && mark > 0) {double speed = dataLength / (cost + 0.0f);
if (speed < CALL_SPEED_GOOD_BENCH_MARK) { // 利用 speed,将申请体小的申请分数升高
mark = speed / CALL_SPEED_GOOD_BENCH_MARK * mark;
}
}
return mark;
}
IP 总分
IP 总分有两次策略:累计计分、刹时计分
累计计分
以后网络环境下(WiFi/ 蜂窝)的所有申请的分值的加和。
刹时计分
以后网络环境下(WiFi/ 蜂窝)的以后申请的分值就是 IP 的最终得分。
抉择 IP
申请收回的时候依据拿到的 IP 组依照 IP 的跑分拿最高分作为当成申请的 IP。
整体流程图
4. 小结与瞻望
网络安全不容小觑,各大厂商都在尽力去通过技术手段来去保护网络安全,来给用户提供一个安全可靠的网络环境。咱们也心愿苹果在后续能够在 DNS 相干方面提供更凋谢可由开发人员来去实现策略的 API,在保障网络安全根底上又能让开发人员能有肯定的灵活性。针对文中 Cronet 的应用因为还在灰度推动中,等推全后也将梳理篇 Cronet 接入带来的利好及坑点来和大家交换。
参考资料
[1] WWDC – 10079
[2] DNSSEC 协定
[3] DNS 劫持
[4] DNS 坑骗
[5] Enable encrypted DNS
[6] Cronet 网络申请流程
本文公布自网易云音乐技术团队,文章未经受权禁止任何模式的转载。咱们长年招收各类技术岗位,如果你筹备换工作,又恰好喜爱云音乐,那就退出咱们 grp.music-fe(at)corp.netease.com !