定义: 一种用于TCP/IP应用程序的
分布式的数据库
。 提供主机名字和IP地址之间的转换以及有关电子邮件的选路信息。 提供了允许服务器和客户程序相互通信的协议。
产生的原因: IP地址不便于记忆,需要名字来进行记忆,名字需要对应的ip进行查找资源。
IP 变成名字, DNS将名字找对应的IP。 (人和机器的相关选择) ——解决IP地址不便于记忆的问题
刚开始:使用一台中心的主机的hosts文件存放对应的域名和ip地址。但是,数量暴增的时候,显示不足。 ——> 产生DNS
域名解析器:客户端的程序包含 (eg:个人电脑)
域名服务器:DNS服务器
<netdb.h>
// 通过域名获取ip地址
struct hostent *gethostbyaddr(const void *, socklen_t, int);
// 通过ip地址获取域名
struct hostent *gethostbyname(const char *);
+ (NSString *)getIpv4AddressFromHost: (NSString *)host {
const char * hostName = host.UTF8String;
struct hostent * phost = gethostbyname(hostName);
if ( phost == NULL ) { return nil; }
struct in_addr ip_addr;
memcpy(&ip_addr, phost->h_addr_list[0], 4);
char ip[20] = { 0 };
inet_ntop(AF_INET, &ip_addr, ip, sizeof(ip));
return [NSString stringWithUTF8String: ip];
}
解析器:通常是应用程序的一部分。 解析器并不像TCP/IP 协议那样是操作系统的内核。
在一个应用程序请求TCP打开一个连接或使用UDP发送一个数据报之前。 必须将一个主机名转换为一个IP地址。
操作系统内核中的TCP/IP协议族对于DNS一点都不知道。
—— 也就是TCP/IP 协议族里面根本就不管DNS的解析。 这个过程在请求的之前就处理了。
DNS基础
每个结点(圆圈)有一个至多63个字符长的标识。【树根的结点没有标识的特殊结点】
!!! 主要区分域名和标识这两个概念。
域名:该结点-> 最高层结点 串联起来标识,用点分隔。 [叶子——树根]
域名树中的每个节点必须有唯一的域名(xxx.yyy.zzz) , 但是域名树中的不同结点的可以使用相同的标识.(xxx)
上图: 顶级域名被分为三个部分:
1)arpa :是一个用作地址到名字转换的特殊域
2)普通域(组织域名):7个3字符长的普通域。
3)地理域(国家域):所有2字符长的域均是基于ISO3166中定义的国家代码。
《1》上面的普通域和地理域并不是绝对的通过字数来区分的。
《2》 许多国家将它们的二级域组织成类似于普通域的结构:eg,.ac.uk 是英国研究机构的二级域名。.co.uk 则是英国商业机构的二级域名。
没有哪个机构来管理域名树中的每个标识, 相反,只有一个机构,即网络信息中心NIC负责分配顶级域和委派其他指定地区域的授权机构。 —— 也就是NIC 只是负责上面一层。
sun.tuc.noao.edu.
下面是有关与服务器的过程, 这个过程需要细化之后进一步了解
这里的
名字服务器
可以称为域名服务器
。
一个独立管理的DNS子树成为一个区域(zone)。一个常见的区域是一个二级域, eg:noao.edu 。 许多二级域将它们的区域划分成为更小的区域。
一旦一个区域的授权机构被委派后,由它负责向该区域提供多个域名服务器。 当一个新系统加入到一个区域中时, 该区域的DNS管理者为该新系统申请一个域名和一个ip地址,并将它们加到域名服务器的数据库中。这就是授权机构存在的必要性。 —— 也就是上一层区域「DNS服务器」记录下一层区域的域名和ip地址。 ——
注册记录和授权
一个域名服务器负责一个或多个区域。
一个区域的管理则会必须为该区域提供一个主域名服务器和至少一个辅助域名服务器。 主、辅域名服务器必须是独立和冗余的, 以便当某个域名服务器发生故障时不会影响该区域的名字服务。 —— 容灾
【当一个新主机加入一个区域时候,区域管理者将适当的信息(最少包括名字和ip地址)加入到运行在主域名服务器上的一个磁盘中, 然后通过主名字服务器重新调用入它的配置文件。 辅名字服务器定时(通常每隔3小时)向主名字服务器询问是否有新数据。 如果有新数据,则通过区域传送方式获得新数据。 】
当一个域名服务器没有请求的信息时,它将如何处理?
它必须与其他的域名服务器联系。 (这正是DNS分布式特性) 然而, 并不是每个域名服务器都知道如何同其他域名服务器联系。
相反, 每个域名服务器必须知道如何同根的名字服务器联系。 1993年4月时候有8个根名字服务器, 所有的主名字服务器都必须知道根服务器的IP地址(这些IP地址在主名字服务器的配置文件中,主服务器必须知道根服务器的ip地址,而不是它们的域名)。 根服务器则知道所有二级域中的每个授权名字服务器与根服务器联系,根据服务器告诉它与另一个名字服务器联系。 【这里到底是根还是上一层的结点?】
DNS 高速缓存:查找到的主机名+ip地址,在当前服务器中缓存,下一次直接就从缓存里面取。
14.3 DNS 的报文格式
定义了一个用于
查询
和响应
的报文格式
报文组成: 12字节长度的首部 + 4个长度的可变的字段组成。
标识:
由客户程序设置并由服务器返回结果。 客户程序通过它来确定响应与查询是否匹配。
QR : 1bit , 0标识查询报文, 1表示响应报文
opcode 是一个4bit字段: 通常值位0(标准查询),其他值位1(反向查询) 和2(服务器状态请求)
AA :1bit , 表示“授权回答(authoritative answer)” 。 该名字服务器是授权与该域的。
TC : 1bit, 表示“可截断的(truncated)” 。 使用UDP时候, 它表示应当应答的总长度超过512字节时, 只返回前512个字节。
RD : 1bit, 表示“期望递归(recursion desired)” 。 在一个查询中设置,并在响应中返回。 这个标志告诉域名服务器必须处理这个查询, 也称为递归查询。 如果为0,且被请求的域名服务器没有一个授权回答, 它就返回一个能解答该查询的其他名字服务器列表, 这称为迭代查询。
RA : 1bit , 表示“可用递归”。如果域名服务器支持递归查询,则在响应中将该bit设置为1。 在后面的例子中可看到大多数域名服务器提供递归查询,除了某些根服务器。
zero: 3bit 必须为0
rcode :4bit , 返回码字段。 通常的值位0(没有差错)和3(名字差错)。名字差错只有从一个授权域名服务器返回,它表示在查询中指定的域名不存在。
4个16bit字段:最后4个边长字段中包含的条目数。 对于查询报文,问题(question)数通常是1, 而其他3项均为0。类似地,对于应答柏爱文,回答数至少是1,剩下的两项可以是0或非0.
14.3.1 DNS 查询报文中的问题部分
查询名(要查找的名字)
:它是一个或多个标识符的序列。 每个标识符以首字节的计数值来说明随后标识符的字节长度, 每个名字以最后字节为0结束,长度为0的标识符是根标识符。
计数字节的值必须是0~63的数, 因为标识符的最大长度仅为63(将会看到:计数字节的最高量比特为1, 即值192~255 , 将用于压缩格式)。 不像我们已经看到的许多其他报文格式,该字段无需以整32bit边界结束,即无需填充字节。
每个问题有一个查询类型,而每个响应也有一个类型。 大约有20个不同的类型值。 查询类型是类型的一个超集(superset):
A类型:期望获得查询名的IP地址
PTR : 请求获得一个ip地址对应的域名。 一个指针查询
14.3.2 DNS 响应报文中的资源记录部分
DNS报文中最后的三个字段:回答字段、授权字段和附加信息字段
,均采用一种成为资源记录RR(Resource Record)的相同格式。
域名: 记录中资源数据对应的名字。 它的格式和前面介绍的查询名字段格式相同
类型:说明RR的类型码。 它的值和前面介绍的查询类型值是一样的。类通常为 1, 指Internet数据
生存时间字段:客户端程序保留该资源记录的秒数。 资源记录通常的生存时间值为2天。
资源数据长度: 说明资源数据的数量。 该数据的格式依赖于类型字段的值。 对于类型1(A记录)资源数据是4字节的IP地址。
实践操作
域名解析器是客户程序的一部分,并在TCP连接之前,域名解析器就能够通过域名服务器获取IP地址。
查询过程中的递归和迭代的理解:
DNS系统解析视频: 理解递归和迭代的过程
DNS 系统查询过程的递归和查询
DNS 和hosts关系
14.5 指针查询
ip 地址 ——> 域名
「查看第一个图」, 顶级域arpa, 以及它下面的in-addr域。
当一个组织后加入internet, 并获得DNS域名空间的授权,eg:noao.edu , 则它们也获得了对应IP地址的in-addr.arpa 域名空间的授权。 所以,对于IP地址为140.252.13.33 的主机来说, 它的DNS名字为33.13.252.140.in-addr.arpa 。
必须写出4字节的IP地址, 因为授权的代表是基于网络号: A类地址是第一字节,B类地址是1、2字节,c类地址是1、2、3字节。 IP地址的第1字节一定位于in-addr的下一级, 但是FQDN确实自树底往上书写的。 如果FQDN由顶往下书写,则这个IP地址的DNS名字将是arpa.in-addr.140.252.13.33 , 而它对应的域名将是edu.noao.tuc.sun 。 —— 也就是DNS中使用了独立的树来处理ip到域名的转换
14.5.2 主机名检查
eg: 从未知的IP地址使用匿名FTP访问服务器。 (没某些服务器需要客户的IP地址来获得在DNS中的指针记录)
某些厂商将改项姜茶自动并入其名字解析器的例程中, 特别是函数gethostbyaddr。 这使得任何使用名字解析器的程序均可获得这种见擦汗, 而无需再应用中认为的进行这项检查。
14.6 资源记录
14.7 高速缓存
DNS服务器里面实现了缓存,提高了速率。
14.8 用UDP还是TCP
端口: 53
DNS支持UDP和TCP的访问。 目前看到的都是使用UDP
什么时候采用UDP还是TCP
TCP:
《1》 返回数据截断的时候:
当域名解析器发出一个查询请求, 并且返回响应中的TC(删除标志)为1时,意味着响应的长度超过了512个字节,而仅返回512字节。 这个时候域名解析器通常使用TCP重发原来的查询请求,它允许返回的响应超过512个字节。 既然TcP能够将用户的数据流分为一些报文段,它就能用多个报文段来传送任意长度的用户数据。
《2》一个域的辅助域名服务器在启动时候, 将从该域的主名字服务器执行区域传送。 我们也说过辅助服务器将定时(通常是3个小时)向主服务器精心查询以便于了解主服务器数据是否发生变动。 如果有变动, 将执行一次区域传送。 预取传送将使用TCP, 因为这里传送的数据远比一个查询或响应多的多。
UDP: DNS主要施一公UDP, 无论是域名解析器还是域名服务器都必须自己处理超时和重传。 不像其他的使用UDP的Internet的应用(TFTP、BOOTP和SNMP),大部分操作集中在局域网上, DNS查询和响应通常经过广域网。分组丢失率和往返时间的不确定性在广域网上比局域网更大。 这样DNS客户程序,一个号的重传和超时程序就显得更重要了。
14.9 一个完整的例子过程
小结
DNS: 层次树是组成DNS域名空间的基本组织形式
应用程序通过名字解析器将一个主机名转换成为一个IP地址,也可将一个IP地址转换为与之对应的主机名。 名字解析器将向一个本地名字服务器发出查询请求,这个名字服务器可能通过某个根名字服务器或其他名字服务器完成这个查询。
所有的DNS查询和响应都有相同的报文格式。 这个报文格式中包含查询请求和可能的回答资源记录、授权资源记录和附加资源记录。 通过许多例子了解了名字解析器的配置文件以及DNS的优化措施:指向域名的指针(减少报文的长度)、差教训结果的告诉缓存、in-addr.arpa 域(查找ip地址对应的域名)以及返回的附加资源记录(避免主机重发同一个查询请求)
DNS备份域名服务器—— 提供备灾能力
所有的域名服务器都必须注册根域名服务器的IP地址。 ——因为DNS根据IP地址进行检索时, 需要从根域名服务器开始按顺序进行。
解析器(Resolver)
:进行DNS查询的主机和软件。 eg: 个人电脑
??? 这里有个问题: 找不到是直接到总域名根服务器还是上一层根服务器呢?
上一层根域名服务器进行查询处理
解析器和域名服务器将最新了解到的信息保存在缓存里。 可以减少每次查询时的性能消耗。
主机名与IP地址的对应信息叫做A记录。 反之,从ip地址检索主机名称的信息叫做PTR。 上层或下层域名服务器IP地址的映射叫做NS记录。
————————————————
小结:
1> 域名查找ip地址, 在解析器到本地DNS服务器的过程是递归,在root 到查找对应的DNS服务器获取ip地址的过程是迭代。
2> ip地址查找域名:通过rapa-> in-addr 这个独立的树来进行查找的。
扩展:
1、DNS的解析过程, 域名转化为ip地址,以及ip地址转化为域名
上面小结
2、DNS 劫持/污染是什么? 为什么会被劫持
在DNS解析的时候,通过某种途径,返回非预期的ip地址。可能返回的结果是:一些弹窗、还有一些其他网站的复制等。 这个也是黑客攻击的方式。
3、移动端为什么需要httpDNS?
HTTPDNS深度解析
全局精确流量调度新思路-HttpDNS服务详解
移动端为什么需要HTTPDNS?
可以解决传统的DNS劫持,访问时间延迟等问题。
1》local DNS 劫持:
由于httpDNS是通过IP直接请求http获取服务区A记录地址,不存在向本地运行商询问domain解析过程,所以从根本避免了劫持问题。
2》平均访问延迟下降:
由于是IP地直接访问,省掉了一次domain解析过程,通过智能算法排序后找到最快节点进行访问。
3》用户链接失败率下降:通过算法降低以往失败率过高的服务器排序,通过时间近期访问过的数据提高服务器排序,通过历史访问成功记录提高服务器排序。
iOS中怎么能简单判断自己被DNS劫持了? 是否需要先判断劫持了再走httpdns