DNS查询相关

本文同时发表在https://github.com/zhangyachen/zhangyachen.github.io/issues/45

一种简单的设计方式是在因特网上使用一个DNS服务器,该服务器包含所有的映射。在这种集中式设计中,客户端将所有的查询发往同一台的DNS服务器。但是,这种设计方式的问题如下:

  • 单点故障
  • 通信容量:必须处理所有查询
  • 远距离的集中式数据库:如果将单台DNS服务器放在纽约,那么在澳大利亚的的查询必须传播到地球的另一端,中间也许还要经过拥塞的链路。
  • 维护

基于以上几点,DNS采用分布式设计方案。

分布式、层次数据库

为了处理规模问题,DNS使用了大量的DNS服务器,他们以层次方式组织,并且分布在全世界的范围内。大致来说,有三种类型的DNS服务器:

  • 根DNS服务器:有13个,编号为A到M。尽管我们将这13台DNS服务器中的每个都视为单台服务器,但是实际上他们都是冗余服务器,以提供安全性和可靠性。
  • 顶级域DNS服务器:负责顶级域名(com,org,net等)和所有国家的顶级域名(jp,cn,uk)
  • 权威DNS服务器:在因特网上具有公共可访问主机(如Web服务器和邮件服务器)的每个组织机构必须提供公共可访问的DNS记录,这些记录将主机名字映射为IP地址。由组织机构的权威DNS服务器负责保护这些DNS记录。组织机构可以选择实现他自己的权威DNS服务器来保持这些记录,另一种方法是支付费用将这些记录存储在某个服务提供商的权威DNS服务器中。

根,TLD和权威DNS服务器都处在DNS层级结构中,还有另外一种重要的DNS,叫作本地DNS服务器。本地DNS服务器严格来说并不属于DNS服务器的层级结构,但是它对DNS层级结构是很重要的。主机的本地DNS服务器通常邻近本主机。对于机构ISP而言,本地DNS服务器可能就与主机在同一个局域网中,对于居民区ISP来说,本地DNS服务器通常与主机相隔不超过几个路由器。当主机发出DNS请求时,该请求被发往本地DNS服务器,它起着代理的作用,并将该请求转发到DNS服务器层级结构中。

举个如上图的例子,主机cis.poly.edu想要知道主机gais.cs.umass.edu的IP地址,主机先向本地DNS服务器发送查询报文,本地DNS服务器将报文转发到根DNS服务器,根DNS服务器注意到edu前缀并向本地DNS服务器返回负责edu的TLD的IP地址列表。本地DNS服务器再次向这些TLD服务器发送查询报文,该TLD服务器注意到umass.edu前缀,并用权威DNS服务器的IP地址进行响应,我们先假设权威服务器的IP地址是dns.umass.edu。最后,本地DNS服务器直接向权威服务器重发查询报文,并获得目的主机的IP。在此过程中,共发送8份报文:4份查询报文和4份回答报文。

在上面的分析过程中,我们假设TLD服务器知道每台主机的权威DNS服务器的IP地址,但是一般情况下不是这样的。相反,TLD服务器只知道中间的某个DNS服务器,该中间的DNS服务器依次才能知道用于该主机的权威DNS服务器的IP地址。同样是上面的例子,当中间的DNS服务器收到对某主机的请求时,该主机名是以cs.umass.edu结尾的,它向本地DNS服务器返回dns.cs.umass.edu的IP地址(上面的例子是dns.umass.edu),后者是所有以cs.umass.edu结尾的主机的权威DNS服务器。本地DNS服务器再向dns.cs.umass.edu发送查询,获得结果。再这个例子中,共发送10份报文。

上面的例子运用了迭代查询和递归查询。从请求主机到本地DNS是递归,后继3个查询都是迭代查询。理论上讲,任何查询既可以是迭代也可以是递归。下图的查询都是递归查询。

实际中,查询通常是请求主机到本地DNS是递归,其余是迭代。

DNS缓存

为了改善性能并减少在因特网上到处传输的DNS报文数量,DNS广泛的使用了缓存技术。在请求链中,当一个DNS服务器收到一个DNS回答,DNS服务器能将回答中的信息缓存在本地存储器。DNS服务器会在一段时间后(通常设置为2天)将丢弃缓存的信息。

DNS记录

实现DNS分布式数据库的所有DNS服务器共同存储着资源记录(Resource Record,RR)。RR提供了主机名到IP地址的映射,每个DNS回答报文包含了一条或者多条资源记录。

资源记录是一个包含了下列字段的4元组:

(Name,Value,Type,TTL)

TTL是该记录的生存时间,决定了资源记录应当从缓存中删除的时间下面给出的例子中我们先忽略TTL字段。Name和Value取决于Type:

  • 如果Type=A,则Name是主机名,Value是主机名的IP地址。因此,一条类型为A的资源记录提供了标准的主机名到IP地址的映射。例如,(relay1.bar.foo.com,145,37,93,126,A)就是一条A记录。
  • 如果Type=NS,则Name是域(如foo.com),而Value是知道如何获得该域中主机IP地址的权威DNS主机名(也就是用来指定该域名由哪个DNS服务器来进行解析。)。这个记录用于沿着查询链路进一步路由DNS查询。例如,(foo.com,dns.foo.com,NS)就是一条类型为NS是记录。
  • 如果Type=CNAME,则Value是别名为Name的主机对应的规范主机名(有着复杂的主机名的主机可以拥有一个或者多个别名。主机的本名叫作规范主机名。相当于一个人的本名和若干个外号),该记录能够向请求主机提供一个主机名对应的规范主机名。
  • 如果Type=MX,则Value是别名为Name的邮件服务器的规范主机名。例如,(foo.com,mail.bar.foo.com,MX)就是一条MX记录。

如果一台DNS服务器是某特定主机的权威DNS服务器,那么该DNS服务器就会包含一条A型记录。(即使不是DNS服务器,也可能在缓存中有A型记录)。如果DNS服务器不是某个主机名的权威DNS服务器,那么该主机将包含一条NS记录,还将包含一条A记录。例如,edu TLD服务器不是主机gaia.cs.umass.edu的权威DNS服务器,则该服务器将包含一条包括主机cs.umass.edu的域记录,如(umass.edu,dns.umass.edu,NS),还包括一条A记录,如(dns.umass.edu,128.119.40.111,A)。

dig工具

工具软件dig可以显示整个DNS查询过程。

[[email protected] ~]# dig zhidao.baidu.com

输出如下信息:

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.37.rc1.el6 <<>> zhidao.baidu.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 189
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;zhidao.baidu.com.      IN  A

;; ANSWER SECTION:
zhidao.baidu.com.   5   IN  CNAME   iknow.baidu.com.
iknow.baidu.com.    5   IN  CNAME   iknow.n.shifen.com.
iknow.n.shifen.com. 5   IN  A   123.125.115.90
iknow.n.shifen.com. 5   IN  A   123.125.65.91

;; Query time: 28 msec
;; SERVER: 192.168.183.2#53(192.168.183.2)
;; WHEN: Thu Jul  7 01:44:35 2016
;; MSG SIZE  rcvd: 115

第一段是查询参数和统计:

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.37.rc1.el6 <<>> zhidao.baidu.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 189
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0

第二段是查询内容:

;zhidao.baidu.com.      IN  A

查询zhidao.baidu.com的A记录。

第三段是DNS服务器的答复:

;; ANSWER SECTION:
zhidao.baidu.com.   5   IN  CNAME   iknow.baidu.com.
iknow.baidu.com.    5   IN  CNAME   iknow.n.shifen.com.
iknow.n.shifen.com. 5   IN  A   123.125.65.91
iknow.n.shifen.com. 5   IN  A   123.125.115.90

第四段是DNS服务器的一些传输信息:

;; Query time: 29 msec
;; SERVER: 192.168.183.2#53(192.168.183.2)
;; WHEN: Thu Jul  7 02:09:40 2016
;; MSG SIZE  rcvd: 115

上面结果显示,本机的DNS服务器是192.168.183.2,查询端口是53(DNS服务器的默认端口),以及回应长度是115字节。

如果不想看到这么多内容,可以使用+short参数:

[[email protected] ~]# dig +short zhidao.baidu.com
iknow.baidu.com.
iknow.n.shifen.com.
123.125.115.90
123.125.65.91

+trace参数可以显示DNS的整个分级查询过程:

[[email protected] ~]# dig +trace zhidao.baidu.com

第一段列出根域名.的所有NS记录,即所有根域名服务器。

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.37.rc1.el6 <<>> +trace zhidao.baidu.com
;; global options: +cmd
.           5   IN  NS  l.root-servers.net.
.           5   IN  NS  b.root-servers.net.
.           5   IN  NS  j.root-servers.net.
.           5   IN  NS  m.root-servers.net.
.           5   IN  NS  g.root-servers.net.
.           5   IN  NS  h.root-servers.net.
.           5   IN  NS  c.root-servers.net.
.           5   IN  NS  i.root-servers.net.
.           5   IN  NS  f.root-servers.net.
.           5   IN  NS  d.root-servers.net.
.           5   IN  NS  k.root-servers.net.
.           5   IN  NS  a.root-servers.net.
.           5   IN  NS  e.root-servers.net.
;; Received 228 bytes from 192.168.183.2#53(192.168.183.2) in 1544 ms

根据内置的根域名服务器IP地址,DNS服务器向所有这些IP地址发出查询请求,询问zhidao.baidu.com顶级域名服务器com.的NS记录。最先回复的根域名服务器将被缓存,以后只向这台服务器发请求。

com.            172800  IN  NS  h.gtld-servers.net.
com.            172800  IN  NS  b.gtld-servers.net.
com.            172800  IN  NS  f.gtld-servers.net.
com.            172800  IN  NS  e.gtld-servers.net.
com.            172800  IN  NS  d.gtld-servers.net.
com.            172800  IN  NS  a.gtld-servers.net.
com.            172800  IN  NS  j.gtld-servers.net.
com.            172800  IN  NS  m.gtld-servers.net.
com.            172800  IN  NS  i.gtld-servers.net.
com.            172800  IN  NS  g.gtld-servers.net.
com.            172800  IN  NS  k.gtld-servers.net.
com.            172800  IN  NS  c.gtld-servers.net.
com.            172800  IN  NS  l.gtld-servers.net.
;; Received 494 bytes from 192.112.36.4#53(192.112.36.4) in 3203 ms

上面结果显示.com域名的13条NS记录,同时返回的还有每一条记录对应的IP地址。

然后,DNS服务器向这些顶级域名服务器发出查询请求,询问zhidao.baidu.com的次级域名baidu.com的NS记录。

baidu.com.      172800  IN  NS  dns.baidu.com.
baidu.com.      172800  IN  NS  ns2.baidu.com.
baidu.com.      172800  IN  NS  ns3.baidu.com.
baidu.com.      172800  IN  NS  ns4.baidu.com.
baidu.com.      172800  IN  NS  ns7.baidu.com.
;; Received 204 bytes from 192.43.172.30#53(192.43.172.30) in 692 ms

然后,DNS服务器向上面这四台NS服务器查询math.stackexchange.com的主机名。

zhidao.baidu.com.   1200    IN  CNAME   iknow.baidu.com.
iknow.baidu.com.    1200    IN  CNAME   iknow.n.shifen.com.
n.shifen.com.       86400   IN  NS  ns1.n.shifen.com.
n.shifen.com.       86400   IN  NS  ns3.n.shifen.com.
n.shifen.com.       86400   IN  NS  ns5.n.shifen.com.
n.shifen.com.       86400   IN  NS  ns4.n.shifen.com.
n.shifen.com.       86400   IN  NS  ns2.n.shifen.com.
;; Received 253 bytes from 220.181.38.10#53(220.181.38.10) in 662 ms

dig命令的-x参数用于查询PTR记录(用于从IP地址查询域名)

[[email protected] ~]# dig -x 192.30.252.153

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.37.rc1.el6 <<>> -x 192.30.252.153
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44848
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;153.252.30.192.in-addr.arpa.   IN  PTR

;; ANSWER SECTION:
153.252.30.192.in-addr.arpa. 5  IN  PTR pages.github.com.

;; Query time: 619 msec
;; SERVER: 192.168.183.2#53(192.168.183.2)
;; WHEN: Thu Jul  7 05:40:10 2016
;; MSG SIZE  rcvd: 75

其他DNS查询工具

host
[[email protected] ~]# host zhidao.baidu.com
zhidao.baidu.com is an alias for iknow.baidu.com.
iknow.baidu.com is an alias for iknow.n.shifen.com.
iknow.n.shifen.com has address 123.125.115.90
iknow.n.shifen.com has address 123.125.65.91
nslookup

用于互动式地查询域名记录。

[[email protected] ~]# nslookup
> www.baidu.com
Server:     192.168.183.2   //连上的DNS服务器
Address:    192.168.183.2#53

Non-authoritative answer:     //没有从权威服务器中寻找答案,即从上连DNS服务器的本地缓存中读取出的值,而非实际去查询到的值
www.baidu.com   canonical name = www.a.shifen.com.
Name:   www.a.shifen.com
Address: 61.135.169.125
Name:   www.a.shifen.com
Address: 61.135.169.121

更详细的使用方法:http://roclinux.cn/?p=2441

DNS报文

DNS有2中报文:查询和回答报文。并且具有相同的格式。

各字段语义如下:

  • 前12个字节是首部区域。
  • 标识符是一个16比特的数字,用于标识该查询,该标识符会被复制到回答报文中,以便让客户机用它来匹配发送的请求和收到的回答。
  • 标志字段中含有若干标志。

    • QR(1比特):查询/响应的标志位,1为响应报文,0为查询报文。
    • opcode(4比特):定义查询或响应的类型(若为0则表示是标准的,若为1则是反向的,若为2则是服务器状态请求)。
    • AA(1比特):当某DNS服务器正好是被请求主机的权威DNS服务器时,1比特的“权威的”标志位被置在回答报文中。
    • TC(1比特):截断标志位。1表示响应已超过512字节并已被截断。
    • RD(1比特):这个比特位被请求设置,应答的时候使用的相同的值返回。如果设置了RD,就建议域名服务器进行递归解析,递归查询的支持是可选的。
    • RA(1比特):这个比特位在应答中设置或取消,用来代表服务器是否支持递归查询。
    • zero(3比特):保留字段。
    • rcode(4比特):返回码,表示响应的差错状态,通常为0和3。
    • 0 成功的响应
    • 1 格式错误--域名服务器无法解析请求,因为请求消息格式错误
    • 2 服务器错误--域名服务器因为内部错误无法解析该请求
    • 3 名字错误-- 只在权威域名服务器的响应消息中有效,标示请求中请求的域不存在
    • 4 域名服务器不支持请求的类型
    • 5 域名服务器因为策略的原因拒绝执行请求的操作。例如域名服务器不会为特定的请求者返回查询结果,或者域名服务器不会为特定的请求返回特定的数据
  • 4个数量字段:表示首部后面的4类数据区域出现的数量。
  • 问题区域包含着正在进行的查询信息。格式如下:

该区域包括:

  • 查询名字段:长度不定,一般为要查询的域名(也会有IP的时候,即反向查询)。此部分由一个或者多个标示符序列组成,每个标示符以首字节数的计数值来说明该标示符长度,每个名字以0结束。计数字节数必须是0~63之间。该字段无需填充字节。例如查询域名名为gemini.tuc.noao.edu的话,查询名字段如下:

  • 查询类型字段(2字节):它指出有关该名字的正被询问的问题类型,例如主机地址是与一个名字相关联(类型A)还是与某个名字的邮件服务器相关联(类型MX)。
  • 查询类(2字节):通常为1,指Internet数据。
  • 回答区域包含了对最初请求的名字的资源记录。格式如下:

  • 域名字段(不定长或2字节):记录中资源数据对应的名字,它的格式和查询名字段格式相同。
  • 类型(2字节)、类(2字节):含义与查询问题部分的类型和类相同。
  • 生存时间(4字节):该字段表示资源记录的生命周期(以秒为单位),一般用于当地址解析程序取出资源记录后决定保存及使用缓存数据的时间。
  • 资源数据长度(2字节):表示资源数据的长度。
  • 资源数据:该字段是可变长字段,表示按查询段要求返回的相关资源记录的数据。

参考资料:

《计算机网络-自顶向下方法(原书第4版)》

http://blog.chinaunix.net/uid-24875436-id-3088461.html

http://www.ruanyifeng.com/blog/2016/06/dns.html

http://www.cnblogs.com/xiaoluo501395377/archive/2013/06/03/3116064.html

https://msdn.microsoft.com/zh-cn/library/cc775637(v=ws.10).aspx

http://www.cnblogs.com/cobbliu/archive/2013/04/02/2996333.html

时间: 2024-10-09 19:47:33

DNS查询相关的相关文章

Java DNS查询内部实现

源码分析 在Java中,DNS相关的操作都是通过通过InetAddress提供的API实现的.比如查询域名对应的IP地址: String dottedQuadIpAddress = InetAddress.getByName( "blog.arganzheng.me" ).getHostAddress(); 或者反过来IP对应域名: InetAddress[] addresses = InetAddress.getAllByName("8.8.8.8"); // i

在 Linux/Unix/Mac 下清除 DNS 查询缓存

在MS-Windows下,你可以使用ipconfig命令来清除dns缓存.然而,Linux和Unix提供了不同的方法来清除缓存.Linux可以运行 nscd 或者 BIND 或者 dnsmasq 作为名称服务缓存守护进程.大型或者工作组服务器可能使用BIND或者dnsmasq作为专用缓存服务器来加速查询. 如何: 清除 nscd dns 缓存 Nscd 会缓存libc发起的名称服务的请求.如果把检索NSS数据看做很慢,那么nscd能够显著加快连续访问同一数据的速度,并能提高整个系统的性能.只需重

如何在 Linux/Unix/Mac 下清除 DNS 查询缓存

我在Linux下使用拨号连接上网,频繁的拨号断线造成DNS的问题.我如何在Linux/Unix发行版下使用shell命令清除DNS缓存? 在MS-Windows下,你可以使用ipconfig命令来清除dns缓存.然而,Linux和Unix提供了不同的方法来清除缓存.Linux可以运行 nscd 或者 BIND 或者 dnsmasq 作为名称服务缓存守护进程.大型或者工作组服务器可能使用BIND或者dnsmasq作为专用缓存服务器来加速查询. 如何: 清除 nscd dns 缓存 Nscd 会缓存

DNS查询的工作原理

二.DNS查询的工作原理 1.DNS查询过程按两部分进行     1.名称查询从客户端计算机开始, 并传送给本机的DNS客户服务程序进行解析     2.如果不能再本机解析查询, 可根据设定的查询DNS服务器来解析名称. 2.具体工作过程     1.DNS客户端 --客户端DNS缓存 查找主机文件(有信息)-- 返回信息给DNS客户端     2.DNS客户端 --客户端DNS缓存 查找主机文件 (无信息)--*DNS服务器         ==1区域          ==2通过根目录提示文

Linux socket编程 DNS查询IP地址

本来是一次计算机网络的实验,但是还没有完全写好,DNS的响应请求报文的冗余信息太多了,不只有IP地址.所以这次的实验主要就是解析DNS报文.同时也需要正确的填充请求报文.如果代码有什么bug,欢迎指正啊.代码排版有点乱... 本文有以下内容 DNS报文的填充和解析 利用socket API传输信息 一.填充DNS请求报文 随便百度一下,就可以知道DNS报文的格式.所以这里只介绍如何填充DNS报文. 首先是填充报文首部: ? 1 2 3 4 5 6 7 8 9 /* 填充首部的格式大致相同,下面的

DNS查询流程简介

转载请注明出处:http://blog.csdn.net/luotuo44/article/details/45545059 DNS(domain name system),读者们或多或少都听过,就是可以将域名转换给IP的一个系统.使得我们只需记住域名而非IP就能访问某个网站.当我们在浏览器里面输入一个网址时,浏览器会向本地DNS服务器发出查询请求,本地DNS服务器会把网址对应的IP返回给浏览器.注意:更确切来说,不是本地DNS服务器,而是Windows网络连接里面所配置的DNS服务器.一般我们

基于nodejs的DNS查询工具

开始这个实例之前,我们简单谈一下Node.js吧,Node.js是一个由JavaScript书写而成的强大Web开发框架,它让开发强壮的.伸缩性良好的服务器端Web应用变得更加简单.容易.这种技术诞生于09年末,在一个JavaScript大会上宣布,当时这项在服务器端运行JavaScript技术让所有参会者惊奇,当时这位提出者给出了一个“hello world”的程序. 1 var http = require('http'); 2 var server = http.createServer(

通过线程巧为InetAddress.getByName() DNS查询添加超时限制功能

虽然Socket类有setTimeout()方法,URLConnection有setConnectTimeout()方法,但这都不能给DNS查询过程添加时间限制,也就是说,如果DNS服务器挂了,那么代码就会阻塞几十秒才能抛出异常.我最近就遇到了这个问题,当DNS服务器出问题的时候,setTimeout()设置的超时时间就不起作用了. 经过google,发现Java目前居然还没有现成的API来处理DNS查询超时的问题.不过一个老外的博客上给出了一种曲线救国的方法: public class DNS

linux命令行学习-dig(DNS查询器)

在web开发中,总要熟悉的就是http协议,而发起一个http开始前最先要经历的一个过程就是DNS解析.简单说就是域名如何最终解析到实际服务器ip的过程. 而在研究DNS解析和排除DNS解析类故障问题的时候一个强大的工具就是dig.和他对应的有个比较传统的命令nslookup,不过dig作为更新的命令,其强大而简洁可定制的输出也使得运维其开发人员使用. 实例1(访问服务器本地DNSserver查询根域名服务器):  ~#: dig ; <<>> DiG 9.3.6-P1-RedHa