DNS协议具体解释

DNS协议具体解释

一、前言
  foxmail新版中有一个《邮件特快专递》的功能。起先搞不懂怎样用,后来知道要在 工具->系统选项 那边设置 本地DNSserver的IP地址。
  认为这个新功能蛮好用的。不须要通过SMTP代理,能够直接通过本地往邮箱所在的邮件交换器发送邮件。

在暑假一開始想在VC++中实现这个功能。用IRIS截包后,发现程序后mx8.263.net发送邮箱,不知道这个是什么东西所以作罢。

  后来才想到这个就是263.net的MX记录主机,原来特快专递的原理就是往这个主机上发送数据即可。
  执行nslookup程序:
  set type=mx
  263.net
  有了,有了。得到结果:
  Non-authoritative answer:
  263.net MX preference = 10, mail exchanger = mx06.263.net
  263.net MX preference = 10, mail exchanger = mx08.263.net
  263.net MX preference = 10, mail exchanger = mx09.263.net
  263.net MX preference = 10, mail exchanger = mx11.263.net
  263.net MX preference = 10, mail exchanger = mx12.263.net
  263.net MX preference = 40, mail exchanger = mx03.263.net
  263.net MX preference = 10, mail exchanger = mx01.263.net
  没有错了。就是这个了。后来由于不知道怎么实现nslookup的功能。就放弃了,学了半个多月的C#。后来偶然在网上查找到了一些相关的文档。几次实验。把我的开发过程拿过来分享。我第一次写教程性文档。

所以不规范之处,请大家包涵。本文涉及的域名、邮箱及IP均为真实的。

二、DNS协议原理
  我觉得,要想成为一个好的网络软件程序猿,必须得读懂RFC文档。

由于本文是面向大多广泛程序爱好者,所以我尽量从细节上写,假设高手的话,能够跳过此部分。
  DNS协议的相关RFC文档:
  RFC1034-《DOMAIN NAMES - CONCEPTS AND FACILITIES》
  RFC1035-《DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION》
  网上的计算机用形如 220.162.75.1 这样称为IP地址的数字串来标识一台计算机。而假设每次訪问一台计算机都是通过输入这种东东来訪问,那不就太可怕了?以是出了DNS这种好东东,用要指示其绑定的IP地址。当我们在浏览器内输入 http://zzsy.com 时。浏览器不知道网页该到哪里取,于是就向设定好的DNSserver查询zzsy.com这个域名。

DNSserver会先寻找自己的记录库,假设没有发现就转向上一级DNSserver进行查询(转发请求)。

把找到后的IP告知你的浏览器。

这里边浏览器查询的记录类型是A记录。

RFC1035文档第11页中定义有16种记录类型,而常见的有A(地址)记录、CNAME(别名)记录、MX(邮件交换)记录。我们本篇要关心的是MX记录。


  查询的过程通常是:客户向DNSserver的53port发送UDP报文,DNSserver收到后进行处理。并把结果记录仍以UDP报文的形式返回过来。
  此UDP报文的一般格式:

+---------------------+
| 报文头 |
+---------------------+
| 问题  | 向server提出的查询部分
+---------------------+
| 回答  | server回复的资源记录
+---------------------+
| 授权 | 权威的资源记录
+---------------------+
| 格外的 | 格外的资源记录
+---------------------+

  除了报文头是固定的12字节外。其它每一部分的长度均为不定字节数。
  我们在这边关心的是报文头、问题、回答这三个部分。



  当中报文头的格式:


1 1 1 1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ID |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QDCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ANCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| NSCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ARCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

  好家伙。是什么鬼画符!


  当中最上边是位的数字标识,0-15(注意,后边的10-15写成上下的形式了。一開始我楞没看懂)。
  接下来是:
  ID:占16位,2个字节。此报文的编号,由client指定。

DNS回复时带上此标识。以指示处理的相应请应请求。
  QR:占1位。1/8字节。

0代表查询,1代表DNS回复
  Opcode:占4位,1/2字节。指示查询种类:0:标准查询;1:反向查询;2:server状态查询;3-15:未使用。
  AA:占1位,1/8字节。是否权威回复。


  TC:占1位,1/8字节。由于一个UDP报文为512字节,所以该位指示是否截掉超过的部分。


  RD:占1位,1/8字节。此位在查询中指定,回复时同样。设置为1指示server进行递归查询。
  RA:占1位。1/8字节。

由DNS回复返回指定。说明DNSserver是否支持递归查询。
  Z:占3位,3/8字节。保留字段,必须设置为0。
  RCODE:占4位,1/2字节。由回复时指定的返回码:0:无差错;1:格式错。2:DNS出错。3:域名不存在;4:DNS不支持这类查询;5:DNS拒绝查询;6-15:保留字段。 
  QDCOUNT:占16位,2字节。一个无符号数指示查询记录的个数。
  ANCOUNT:占16位。2字节。一个无符号数指明回复记录的个数。
  NSCOUNT:占16位,2字节。一个无符号数指明权威记录的个数。
  ARCOUNT:占16位。2字节。一个无符号数指明格外记录的个数。

  当中每一个查询的资源记录格式:


1 1 1 1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| |
/ QNAME /
/ /
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QTYPE |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QCLASS |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  QNAME:不定长。表示要查询的域名。(两边的方框用 / 来表示不定长)
  QTYPE:2字节,依据RFC1035及nslookup的帮助文档,我定义下面枚举类型:
enum QueryType //查询的资源记录类型。
{
A=0x01, //指定计算机 IP 地址。
NS=0x02, //指定用于命名区域的 DNS 名称server。
MD=0x03, //指定邮件接收站(此类型已经过时了,使用MX取代)
MF=0x04, //指定邮件中转站(此类型已经过时了,使用MX取代)
CNAME=0x05, //指定用于别名的规范名称。
SOA=0x06, //指定用于 DNS 区域的“起始授权机构”。
MB=0x07, //指定邮箱域名。
MG=0x08, //指定邮件组成员。
MR=0x09, //指定邮件重命名域名。
NULL=0x0A, //指定空的资源记录
WKS=0x0B, //描写叙述已知服务。


PTR=0x0C, //假设查询是 IP 地址,则指定计算机名。否则指定指向其他信息的指针。
HINFO=0x0D, //指定计算机 CPU 以及操作系统类型。
MINFO=0x0E, //指定邮箱或邮件列表信息。
MX=0x0F, //指定邮件交换器。
TXT=0x10, //指定文本信息。

 
AAAA=0x1c,//IPV6资源记录。


UINFO=0x64, //指定用户信息。
UID=0x65, //指定用户标识符。
GID=0x66, //指定组名的组标识符。
ANY=0xFF //指定全部数据类型。


};
QTYPE:2字节。 依据RFC1035及nslookup的帮助文档。我定义下面枚举类型:
enum QueryClass //指定信息的协议组。
{
IN=0x01, //指定 Internet 类别。


CSNET=0x02, //指定 CSNET 类别。(已过时)
CHAOS=0x03, //指定 Chaos 类别。
HESIOD=0x04,//指定 MIT Athena Hesiod 类别。
ANY=0xFF //指定不论什么曾经列出的通配符。
};

  QTYPE中的A,MX,CNAME为经常使用。QCLASS中的IN为经常使用。

  当中每一个回复的记录格式:


1 1 1 1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| |
/ /
/ NAME /
| |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| TYPE |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| CLASS |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| TTL |
| |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| RDLENGTH |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
/ RDATA /
/ /
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

  NAME:回复查询的域名,不定长。
  TYPE:回复的类型。2字节,与查询同义。

指示RDATA中的资源记录类型。
  CLASS:回复的类。2字节,与查询同义。指示RDATA中的资源记录类。
  TTL:生存时间。

4字节,指示RDATA中的资源记录在缓存的生存时间。
  RDLENGTH:长度。2字节,指示RDATA块的长度。
  RDATA:资源记录。

不定义,依TYPE的不同。此记录的格示不同,通常一个MX记录是由一个2字节的指示该邮件交换器的优先级值及不定长的邮件交换器名组成的。



  这边述说一下名称的组合形式。名称由多个标识序列组成。每个标识序列的首字节说明该标识符的长度。接着用是ASCII码表示字符。多个序列之后由字节0表示名字结束。当中某一个标识序列的首字符的长度若是0xC0的话。表示下一字节指示不是标识符序列。而是指示接下部分在本接收包内的偏移位置。
  比方 bbs.zzsy.com 以.分开bbs、zzsy、com三个部分。

每一个部分的长度为3、4、3
  在DNS报文中的形式就如 3 b b s 4 z z s y 3 c o m 0
  假如在包内的第12个字节位置存在有 4 z z s y 3 c o m 0 这种名称了。


  那此时有可能为:3 b b s 4 z z s y 0xC0 0x0C 这种形式。



三、DNS协议实例解说
  说了这么多理论屁话。可能头都有两个大了吧。还是用一个实例的方法来说明吧。
  我选用著名的网络截包及协议分析工具IRIS 4.05,您能够从我的网站上下载:
  http://itboy.cn/data/Iris405Full.rar
  执行Iris。点击菜单的Filters 选 Port标签页 运用 53 port后点确定。


  点击Iris工具栏上的绿色执行图标进行监听。

  在windows中执行nslookup程序。


  输入下面命令:
   set type=mx
  然后返回nslookup程序。
  再输入命令:
   yahoo.com.cn
  会得到
   yahoo.com.cn MX preference = 20, mail exchanger = mx5.mail.yahoo.com
   yahoo.com.cn MX preference = 10, mail exchanger = mta-v1.mail.

=====================================================================


DNS报文格式:




该报文由12字节的首部和4个长度可变的字段组成。
标识字段由客户程序设置并有server返回结果。


16bit的标志字段 例如以下:



QR:0表示查询报文。1表示响应报文
Opcode:通常值为0(标准查询),其它值为1(反向查询)和2(server状态请求)。
AA:表示授权回答(authoritative answer).
TC:表示可截断的(truncated)
RD:表示期望递归
RA:表示可用递归
随后3bit必须为0
Rcode:返回码,通常为0(没有差错)和3(名字差错)
后面4个16bit字段说明最后4个变长字段中包括的条目数。

问题部分:
报文格式:




查询名为要查找的名字,它由一个或者多个标示符序列组成。每一个标示符已首字节数的计数值来说明该标示符长度,每一个名字以0结束。

计数字节数必须是0~63之间。该字段无需填充字节。

如:gemini.tuc.noao.edu



每一个问题有一个查询类型,通常查询类型为A(由名字获得IP地址)或者PTR(获得IP地址相应的域名)
资源记录部分:
报文格式:
DNS最后3个字段。回答字段,授权字段和附加信息字段均採用资源记录RR(Resource Record)的同样格式。




域名是记录中资源数据相应的名字。它的格式和查询名字段格式同样。


类型说明R R的类型码。类通常为1,指I n t e r n e t数据。
生存时间字段是客户程序保留该资源记录的秒数。
资源数据长度说明资源数据的数量。

该数据的格式依赖于类型字段的值。对于类型1(A记录)资源数据是4字节的I P地址。

数据包DNS 查询:(DNS query)
0000  00 19 56 6e 19 bf 00 17   a4 1a b2 e0 08 00 45 00 ..Vn.... ......E.
0010  00 3b ed c6 00 00 80 11   e3 c3 ac 15 0f 04 ac 15 .;...... ........
0020  01 f9 04 a9 00 35 00 27   2f bd 3e 3a 01 00 00 01 .....5.' /.>:....
0030   00 00 00 00 00 00 03 77   77 77 06 67 6f 6f 67 6c .......w ww.googl
0040   65 02 63 6e 00 00 01 00   01                      e.cn.... .   
说明:

前面三段分别为以太网包头,ip包头和UDP包头。
从0020行后面開始为DNS数据包.
3e 3a   为标识字段
01 00 为标志字段。该字段设置了TC表示该报文是可截断的。
00 01   查询报文数量为1。
00 00 00 00 00 00 表示回答,授权和额外信息都为0。
03 77   77 77 06 67 6f 6f 67 6c 65 02 63 6e 00 表示查询的名字为
www.google.com
00 01 为类型,1表示A查询
00 01 为类,1表示Internet数据。



数据包 DNS response (DNS response)
0000  00 17 a4 1a b2 e0 00 19   56 6e 19 bf 08 00 45 00 ........ Vn....E.
0010  00 78 48 af 00 00 7d 11   8b 9e ac 15 01 f9 ac 15 .xH...}. ........
0020  0f 04 00 35 04 a9 00 64   75 db 3e 3a 81 80 00 01 ...5...d u.>:....
0030   00 03 00 00 00 00 03 77   77 77 06 67 6f 6f 67 6c .......w ww.googl
0040   65 02 63 6e 00 00 01 00   01 c0 0c 00 05 00 01 00 e.cn.... ........
0050   00 05 42 00 11 02 63 6e   01 6c 06 67 6f 6f 67 6c ..B...cn .l.googl
0060   65 03 63 6f 6d 00 c0 2b   00 01 00 01 00 00 00 5f e.com..+ ......._
0070   00 04 cb d0 21 65 c0 2b   00 01 00 01 00 00 00 5f ....!e.+ ......._
0080   00 04 cb d0 21 64                               ....!d          
说明:

前面三段分别为以太网包头,ip包头和UDP包头。


3e 3a   为标识字段
81 80  为标志字段,当中设置了QR = 1。RD = 1,RA = 1
00 01  问题数1,00 03  回答数3,其余两个为0。
03 77   77 77 06 67 6f 6f 67 6c 65 02 63 6e 00
表示查询的名字为
www.google.com
00 01 为类型。1表示A查询
00 01 为类。1表示Internet数据。
接下来为回答报文,
c0 0c 为域名指针
00 05  表示CNAME(规范名称)
00 01  类,表示为Internet数据
00 00 05 42  生存时间
00 11  数据长度
02 63 6e   01 6c 06 67 6f 6f 67 6c 65 03 63 6f 6d 00 为数据 cn.l.google.cn
然后接下来两段为另外两个回答。
最后的数据为IP地址


                       转自:http://blog.chinaunix.net/uid-12077794-id-91657.html

posted @ 2017-08-06 13:22  jzdwajue  阅读(742)  评论(0编辑  收藏  举报