1 问题引入:
a) 域名劫持: dns过程中某个环节被攻击/篡改,导致dns结果为劫持者的服务器。例如竞争对手将你方的app下载地址篡改为他方的app下载地址。
b) 对现网用户进行监控时,发现个别用户请求时间为几十秒,而客户端设置的connectTimeout时间为二十秒。
原因:初步判断为dns解析时间耗时过长导致整个接口请求时间远远超过了10s。
解决办法: 自定义dns,设置超时时间。 (使用的的是OkHttp,支持自定义dns)
c) 测试环境dns几十秒,现网正常
原因: 旧的代码里面对url解析为host有bug,当传入一个测试环境地址,例如 10.10.10.10:6026/path,最终解析出来的host为10.10.10.10:6026,
当调用系统的InetAddress.getAllByName("10.10.10.10:6026"),耗时非常长(几十秒)
分析: 首先10.10.10.10:6026不是一个host地址也不是一个ip地址,所以dns是无法解析的。 方法内部会把它当成一个host在到不同的dns服务器上去查找它的ip,最后返回失败。
解决办法: 使用InetAddress中提供的方法来获取host,拒绝自己实现一套
d) no route to host
2 dns过程介绍
2.1 什么是dns
DNS (Domain Name System 的缩写)的作用非常简单,就是根据域名查出IP地址。你可以把它想象成一本巨大的电话本。
举例来说,如果你要访问域名math.stackexchange.com,首先要通过DNS查出它的IP地址是151.101.129.69。
DNS是应用层协议,事实上他是为其他应用层协议工作的,包括不限于HTTP和SMTP以及FTP,用于将用户提供的主机名解析为ip地址。
2.2 主机名结构
举例来说,www.example.com真正的域名是www.example.com.root,简写为www.example.com.。因为,根域名.root对于所有域名都是一样的,所以平时是省略的。
域名的层次结构如下:
主机名.次级域名.顶级域名.根域名
2.3 DNS服务及域名解析过程
1. 假设运行在用户主机上的某些应用程序(如Webl浏览器或者邮件阅读器)需要将主机名转换为IP地址。这些应用程序将调用DNS的客户机端,并指明需要被转换的主机名。(在很多基于UNIX的机器上,应用程序为了执行这种转换需要调用函数gethostbyname())。
2. 用户主机的DNS客户端接收到后,向网络中发送一个DNS查询报文。所有DNS请求和回答报文使用的UDP数据报经过端口53发送.
3. 经过若干ms到若干s的延时后,用户主机上的DNS客户端接收到一个提供所希望映射的DNS回答报文,这个查询结果则被传递到调用DNS的应用程序。
从用户主机上调用应用程序的角度看,DNS是一个提供简单、直接的转换服务的黑盒子。但事实上,实现这个服务的黑盒子非常复杂,**它由分布于全球的大量DNS服务器以及定义了DNS服务器与查询主机通信方式的应用层协议组成。**
DNS查询采用分级查询的方式,所谓"分级查询",就是从根域名开始,依次查询每一级域名的NS记录,直到查到最终的IP地址,过程大致如下。
- 从"根域名服务器"查到"顶级域名服务器"的NS记录和A记录(IP地址)
- 从"顶级域名服务器"查到"次级域名服务器"的NS记录和A记录(IP地址)
- 从"次级域名服务器"查出"主机名"的IP地址、
仔细看上面的过程,你可能发现了,没有提到DNS服务器怎么知道"根域名服务器"的IP地址。回答是"根域名服务器"的NS记录和IP地址一般是不会变化的,所以内置在DNS服务器里面。
下面一张图以www.qq.com为例,介绍了dns的过程:
解析顺序
1) 浏览器缓存
当用户通过浏览器访问某域名时,浏览器首先会在自己的缓存中查找是否有该域名对应的IP地址(若曾经访问过该域名且没有清空缓存便存在);
2) 系统缓存
当浏览器缓存中无域名对应IP则会自动检查用户计算机系统Hosts(linux中是/etc/hosts)文件DNS缓存是否有该域名对应IP;
3) 路由器缓存
当浏览器及系统缓存中均无域名对应IP则进入路由器缓存中检查,以上三步均为客服端的DNS缓存;
4) ISP(互联网服务提供商)DNS缓存
当在用户客服端查找不到域名对应IP地址,则将进入ISP DNS缓存中进行查询。比如你用的是电信的网络,则会进入电信的DNS缓存服务器中进行查找;
5) 根域名服务器
当以上均未完成,则进入根服务器进行查询。全球仅有13台根域名服务器,1个主根域名服务器,其余12为辅根域名服务器。根域名收到请求后会查看区域文件记录,若无则将其管辖范围内顶级域名(如.com)服务器IP告诉本地DNS服务器;
6) 顶级域名服务器
顶级域名服务器收到请求后查看区域文件记录,若无则将其管辖范围内主域名服务器的IP地址告诉本地DNS服务器;
7) 主域名服务器
主域名服务器接受到请求后查询自己的缓存,如果没有则进入下一级域名服务器进行查找,并重复该步骤直至找到正确纪录;
8)保存结果至缓存
本地域名服务器把返回的结果保存到缓存,以备下一次使用,同时将该结果反馈给客户端,客户端通过这个IP地址与web服务器建立链接。
了解了上面的过程就不难理解dns解析一个错误的host为什么需要几十秒的时间了。
DNS的记录类型
域名与IP之间的对应关系,称为"记录"(record)。根据使用场景,"记录"可以分成不同的类型(type),前面已经看到了有A记录和NS记录。
常见的DNS记录类型如下。
(1) A:地址记录(Address),返回域名指向的IP地址。
(2) NS:域名服务器记录(Name Server),返回保存下一级域名信息的服务器地址。该记录只能设置为域名,不能设置为IP地址。
(3)MX:邮件记录(Mail eXchange),返回接收电子邮件的服务器地址。
(4)CNAME:规范名称记录(Canonical Name),返回另一个域名,即当前查询的域名是另一个域名的跳转,详见下文。
(5)PTR:逆向查询记录(Pointer Record),只用于从IP地址查询域名,详见下文。
一般来说,为了服务的安全可靠,至少应该有两条NS记录,而A记录和MX记录也可以有多条,这样就提供了服务的冗余性,防止出现单点失败。
3 dns问题定位工具:dig
a) dig命令的+trace参数可以显示DNS的整个分级查询过程,例如:
dig +trace www.baidu.com
b) 查询每一级域名的NS记录
dig ns com (可以查看包含com域名记录的十三台root服务器信息)
dig ns stackexchange.com (stackexchange.com 次级域名记录的服务器信息)