前言

简介

域名(Domain Name),是由一串用点分隔的名字组成的互联网上某台计算机或某组计算机的标识,它的目的是为了方便人们更简单便捷地访问互联网上的服务。在实际的系统实现中,域名通过DNS(Domain Name System)系统转化为服务器的IP地址,以方便机器通过IP进行寻址和通信。上述行为,我们称之为域名解析

为什么需要DNS解析域名为IP地址

网络通讯大部分是基于TCP/IP的,而TCP/IP是基于IP地址的,所以计算机在网络上进行通讯时只能识别如“202.96.134.133”之类的IP地址,而不能认识域名。我们无法记住10个以上IP地址的网站,所以我们访问网站时,更多的是在浏览器地址栏中输入域名,就能看到所需要的页面,这是因为有一个叫“DNS服务器”的计算机自动把我们的域名“翻译”成了相应的IP地址,然后调出IP地址所对应的网页
作为一次网络通信最前置的环节,域名解析的重要性不言而喻。在传统的基于浏览器的网站访问场景下,域名解析环节由浏览器内核实现,网站开发者无需关心域名解析的细节。But there are always two sides to every coin,一旦域名解析环节发生异常,开发者面对这样的黑盒架构就会显得束手无策,一个很典型的例子即域名劫持问题
进入移动互联网时代,大量的应用基于C/S架构构建。相较于传统的面向浏览器的Web App,C/S架构的应用赋予了我们非常大的软件定制空间,开发者甚至可以渗透到整个应用的底层网络实现当中,域名解析环节的优化因此变为了可能

名词概念

域名系统

域名系统(英文:Domain Name System,缩写:DNS)是一种组织成域层次结构的计算机和网络服务命名系统,它用于TCP/IP网络,它所提供的服务是用来将主机名和域名转换为IP地址的工作。DNS就是这样的一位“翻译官”,它的基本工作原理可用下图来表示。它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网
DNS解析是分布式存储的,比如根域名服务器ROOT DNS,只存储260个顶级域名的DNS服务器的ip地址。顶级域名服务器如.com的DNS服务器,存储的则是一些一级域名的权威DNS服务器地址(如suning.com,qq.com,163.com的DNS)。而suning.com的权威DNS存储的才是具体的主机记录(如A记录,cname记录,txt记录)

根域、顶级域、二级域

DNS系统一般采用树状结构进行组织,以ru.wikipedia.org为例,org为顶级域名,wikipedia为二级域名,ru为三级域名,域名树状组织结构如下图所示
根域名服务器(ROOT)
根服务器主要用来管理互联网的主目录,全世界IPv4根服务器只有13台(这13台IPv4根域名服务器名字分别为“A”至“M”),1个为主根服务器在美国。其余12个均为辅根服务器,其中9个在美国,欧洲2个,位于英国和瑞典,亚洲1个位于日本。根服务器中有经美国政府批准的260个左右的互联网后缀(如.com、.net、.cn等)
顶级域名服务器
负责解析本身顶级域名下一级域名对应的权威DNS服务器地址
localDNS 本地DNS
一般是运营商的dns,主要作用是代理用户进行迭代解析
本地host记录
这个优先级最高可以在自己电脑自定义域名的解析记录,如果本机有就不会再往上迭代。PC的host(C:\Windows\System32\drivers\etc\hosts)

权威DNS

权威DNS即最终决定域名解析结果的服务器,开发者可以在权威DNS上配置、变更、删除具体域名的对应解析结果信息,阿里云云解析即权威DNS服务提供商

递归DNS

递归DNS又称为Local DNS,它没有域名解析结果的决定权,但代理了用户向权威DNS获取域名解析结果的过程。递归DNS上有缓存模块,当目标域名存在缓存解析结果并且TTL未过期时(每个域名都有TTL时间,即有效生存时间,若域名解析结果缓存的时间超过TTL,需要重新向权威DNS获取解析结果),递归DNS会返回缓存结果,否则,递归DNS会一级一级地查询各个层级域名的权威DNS直至获取最终完整域名的解析结果

公共DNS

公共DNS是递归DNS的一种特例,它是一种全网开放的递归DNS服务,而传统的递归DNS信息一般由运营商分发给用户。一个比较典型的公共DNS即Google的8.8.8.8,我们可以通过在操作系统配置文件中配置公共DNS来代替Local DNS完成域名解析流程
在实际的使用过程中,我们通常不需要手工指定自己的Local DNS地址。运营商会通过DHCP协议在系统网络初始化阶段将Local DNS地址分配给我们的计算机。当我们需要使用公共DNS服务时,我们就必须手工指定这些服务的地址。以Linux为例,我们可以通过在'/etc/resolv.conf'中添加Local DNS地址项来改变本机Local DNS的地址

递归查询

主机向本地域名服务器的查询一般都是采用递归查询。所谓递归查询就是:如果主机所询问的本地域名服务器不知道被查询的域名的IP地址,那么本地域名服务器就以DNS客户的身份,向其它根域名服务器继续发出查询请求报文(即替主机继续查询),而不是让主机自己进行下一步查询。因此,递归查询返回的查询结果或者是所要查询的IP地址,或者是报错,表示无法查询到所需的IP地址

迭代查询

本地域名服务器向根域名服务器的查询的迭代查询。迭代查询的特点:当根域名服务器收到本地域名服务器发出的迭代查询请求报文时,要么给出所要查询的IP地址,要么告诉本地服务器:“你下一步应当向哪一个域名服务器进行查询”。然后让本地服务器进行后续的查询。根域名服务器通常是把自己知道的顶级域名服务器的IP地址告诉本地域名服务器,让本地域名服务器再向顶级域名服务器查询。顶级域名服务器在收到本地域名服务器的查询请求后,要么给出所要查询的IP地址,要么告诉本地服务器下一步应当向哪一个权限域名服务器进行查询。最后,知道了所要解析的IP地址或报错,然后把这个结果返回给发起查询的主机

域名解析记录

A记录
A代表的是Address,用来指定域名对应的IP地址,比如将map.baidu.com指定到180.97.34.157,将zhidao.baidu.com指定到180.149.131.245,A记录允许将多个域名解析到一个IP地址,但不允许将一个域名解析到多个IP地址上
MX记录
MX代表的是Mail Exchage,就是可以将某个域名下的邮件服务器指向自己的Mail Server,如baidu.com域名的A记录IP地址是180.97.34.157,如果将MX记录设置为180.97.34.154,即xxx@baidu.com的邮件路由,那么DNS会将邮件发送到180.97.34.154所在的服务器,而正常web请求仍然会解析到A记录的IP地址180.97.34.157
CNAME记录
CNAME指的就是Canonical Name,也就是别名解析,可以将指定的域名解析到其他域名上,而其他域名就是指定域名的别名,整个解析过程称为别名解析。比如将baidu.com解析到itlemon.cn,将csdn.net解析到itlemon.cn,那么itlemon.cn就是baidu.com和CSDN.net的别名
NS记录
就是为某个域名指定了特定的DNS服务器去解析
TXT记录
为某个主机名或者域名设置特定的说明,比如为itlemon.cn设置的的TXT记录为“Lemon的技术笔记”,这个TXT记录为itlemon.cn的说明

域名的解析过程

步骤及原理图

DNS解析过程

检查浏览器缓存中是否缓存过该域名对应的IP地址
用户通过浏览器浏览过某网站之后,浏览器就会自动缓存该网站域名对应的IP地址,当用户再次访问的时候,浏览器就会从缓存中查找该域名对应的IP地址,因为缓存不仅是有大小限制,而且还有时间限制(域名被缓存的时间通过TTL属性来设置),所以存在域名对应的IP找不到的情况。当浏览器从缓存中找到了该网站域名对应的IP地址,那么整个DNS解析过程结束,如果没有找到,将进行下一步骤。对于IP的缓存时间问题,不宜设置太长的缓存时间,时间太长,如果域名对应的IP发生变化,那么用户将在一段时间内无法正常访问到网站,如果太短,那么又造成频繁解析域名
如果在浏览器缓存中没有找到IP,那么将继续查找本机系统是否缓存过IP
如果第一个步骤没有完成对域名的解析过程,那么浏览器会去系统缓存中查找系统是否缓存过这个域名对应的IP地址,也可以理解为系统自己也具备域名解析的基本能力。在Windows系统中,可以通过设置hosts文件来将域名手动绑定到某IP上,hosts文件位置在C:\Windows\System32\drivers\etc\hosts。对于普通用户,并不推荐自己手动绑定域名和IP,对于开发者来说,通过绑定域名和IP,可以轻松切换环境,可以从测试环境切换到开发环境,方便开发和测试。在XP系统中,黑客常常修改他的电脑的hosts文件,将用户常常访问的域名绑定到他指定的IP上,从而实现了本地DNS解析,导致这些域名被劫持。在Linux或者Mac系统中,hosts文件在/etc/hosts,修改该文件也可以实现同样的目的
前两步都是在本机上完成的,所以没有在上面示例图上展示出来,从第三步开始,才正在地向远程DNS服务器发起解析域名的请求
向本地域名解析服务系统发起域名解析的请求
如果在本机上无法完成域名的解析,那么系统只能请求本地域名解析服务系统进行解析,本地域名系统LDNS一般都是本地区的域名服务器,比如你连接的校园网,那么域名解析系统就在你的校园机房里,如果你连接的是电信、移动或者联通的网络,那么本地域名解析服务器就在本地区,由各自的运营商来提供服务。对于本地DNS服务器地址,Windows系统使用命令ipconfig就可以查看,在Linux和Mac系统下,直接使用命令cat /etc/resolv.conf来查看LDNS服务地址。LDNS一般都缓存了大部分的域名解析的结果,当然缓存时间也受域名失效时间控制,大部分的解析工作到这里就差不多已经结束了,LDNS负责了大部分的解析工作
向根域名解析服务器发起域名解析请求
本地DNS域名解析器还没有完成解析的话,那么本地域名解析服务器将向根域名服务器发起解析请求
根域名服务器返回gTLD域名解析服务器地址
本地DNS域名解析向根域名服务器发起解析请求,根域名服务器返回的是所查域的通用顶级域(Generic top-level domain,gTLD)地址,常见的通用顶级域有.com、.cn、.org、.edu等
向gTLD服务器发起解析请求
本地域名解析服务器向gTLD服务器发起请求
gTLD服务器接收请求并返回Name Server服务器
gTLD服务器接收本地域名服务器发起的请求,并根据需要解析的域名,找到该域名对应的Name Server域名服务器,通常情况下,这个Name Server服务器就是你注册的域名服务器,那么你注册的域名的服务商的服务器将承担起域名解析的任务
Name Server服务器返回IP地址给本地服务器
Name Server服务器查找域名对应的IP地址,将IP地址连同TTL值返回给本地域名服务器
本地域名服务器缓存解析结果
本地域名服务器缓存解析后的结果,缓存时间由TTL时间来控制
返回解析结果给用户
解析结果将直接返回给用户,用户系统将缓存该IP地址,缓存时间由TTL来控制,至此,解析过程结束

DNS报文结构

现在的DNS主要还是通过UDP来通讯,大小不超过1500个字节,结构如下:
+--+--+--+--+--+--+--+ | Header | +--+--+--+--+--+--+--+ | Question | +--+--+--+--+--+--+--+ | Answer | +--+--+--+--+--+--+--+ | Authority | +--+--+--+--+--+--+--+ | Additional | +--+--+--+--+--+--+--+
按格式来区分的话,可以分为三部分:头部Header,查询部分Question,应答部分:Answer,Authority,Additional

头部Header

各字段作用
ID: 2个字节(16bit),标识字段,客户端会解析服务器返回的DNS应答报文,获取ID值与请求报文设置的ID值做比较,如果相同,则认为是同一个DNS会话
FLAGS: 2个字节(16bit)的标志字段。包含以下属性
QR: 0表示查询报文,1表示响应报文
opcode: 通常值为0(标准查询),其他值为1(反向查询)和2(服务器状态请求),[3,15]保留值
AA: 表示授权回答(authoritative answer)– 这个比特位在应答的时候才有意义,指出给出应答的服务器是查询域名的授权解析服务器
TC: 表示可截断的(truncated)–用来指出报文比允许的长度还要长,导致被截断
RD: 表示期望递归(Recursion Desired) – 这个比特位被请求设置,应答的时候使用的相同的值返回。如果设置了RD,就建议域名服务器进行递归解析,递归查询的支持是可选的
RA: 表示支持递归(Recursion Available) – 这个比特位在应答中设置或取消,用来代表服务器是否支持递归查询
Z : 保留值,暂未使用
RCODE: 应答码(Response code) - 这4个比特位在应答报文中设置,代表的含义如下
0 : 没有错误
1 : 报文格式错误(Format error) - 服务器不能理解请求的报文
2 : 服务器失败(Server failure) - 因为服务器的原因导致没办法处理这个请求
3 : 名字错误(Name Error) - 只有对授权域名解析服务器有意义,指出解析的域名不存在
4 : 没有实现(Not Implemented) - 域名服务器不支持查询类型
5 : 拒绝(Refused) - 服务器由于设置的策略拒绝给出应答.比如,服务器不希望对某些请求者给出应答,或者服务器不希望进行某些操作(比如区域传送zone transfer)
[6,15] : 保留值,暂未使用
QDCOUNT: 无符号16bit整数表示报文请求段中的问题记录数
ANCOUNT: 无符号16bit整数表示报文回答段中的回答记录数
NSCOUNT: 无符号16bit整数表示报文授权段中的授权记录数
ARCOUNT: 无符号16bit整数表示报文附加段中的附加记录数

Question 查询字段

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ... | | QNAME | | ... | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QTYPE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QCLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
QNAME 8bit为单位表示的查询名(广泛的说就是:域名)
QTYPE 无符号16bit整数表示查询的协议类型
QCLASS 无符号16bit整数表示查询的类,比如,IN代表Internet

应答部分Answer/Authority/Additional

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | NAME | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TYPE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | CLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TTL | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | RDLENGTH | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | RDATA | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
NAME 资源记录包含的域名
TYPE 表示DNS协议的类型
CLASS 表示RDATA的类
TTL 4字节无符号整数表示资源记录可以缓存的时间。0代表只能被传输,但是不能被缓存
RDLENGTH 2个字节无符号整数表示RDATA的长度
RDATA 不定长字符串来表示记录,格式根TYPE和CLASS有关。比如,TYPE是A,CLASS 是IN,那么RDATA就是一个4个字节的ARPA网络地址

常见问题解析