TCP/IP协议网络编程魔法网络知识

TCP/IP协议之DNS

2017-08-06  本文已影响452人  __七把刀__

在使用consul做docker容器服务化的过程中,使用到了dnsmasq做DNS请求转发,于是研究了下DNS协议的一些内容,如有错漏希望大家指正。

1 DNS基础

DNS是一种基于TCP/IP应用的分布式数据库,提供了主机名字和IP地址的转换以及有关电子邮件的选路信息等。在应用看来,对DNS的访问时通过一个地址解析器(resolver)来完成的,在Unix/Linux中,这个解析器主要通过两个函数gethostbynamegethostbyaddr来访问的。

DNS的名字空间和Unix文件系统很相似,具有层次结构,如下图所示。每个节点有个最多63个字符的标识。其中顶层域有arpa(地用作地址到名字转换的特殊域),com,edu,gov,int,mil,net,org(com到org这7个称为普通域或者组织域),cn, ae,us...(这些为国家代码,称为国家域)。许多国家将二级域组织成类似普通域的结构,比如.edu.cn则是我国的教育机构的二级域名,比如大学的官网一般都是这种域名,如 www.hust.edu.cn是华中科大的域名。

没有机构管理域名层次结构中的每个标识,而只有一个机构NIC负责分配顶级域和委派其他指定区域的授权机构。一个独立管理DNS子树的就称为一个区域,一个常见的区域是二级域,比如hust.edu,二级域通常将它们的区域划分为更小的区域,比如大学一般会根据院系划分区域,比如 sse.hust.edu.cn是华中科大的软件学院域名,而cs.hust.edu.cn是华中科大的计算机学院域名。

一旦一个区域的授权机构被委派后,它就要负责给该区域提供多个名字服务器(Linux中的/etc/resolv.conf中的nameserver就是这个)并负责域名的管理。当名字服务器中没有域名信息时,则需要与其他名字服务器联系,当然不是所有的名字服务器都知道如何同其他名字服务器联系,但是他们都知道同根的名字服务器联系。主名字服务器必须知道根服务器的IP地址(注意,不是域名,必须是IP地址),这个可以预先配置好。根服务器则知道所有二级域中的每个授权名字服务器的名字和IP地址,这是一个反复的过程,也就是根服务器告诉了处理请求的名字服务器与另一个名字服务器联系从而最终得到对应信息。

DNS的一个基本特性是使用高速缓存,当一个名字服务器收到映射信息后,会将信息存储在高速缓存中,加速后面相同请求的查找效率。

2 DNS请求流程(递归查询和迭代查询)

先说明一下Linux系统的DNS解析的流程,其他系统除了一些细节不同,大体类似:

递归查询和迭代查询

3 DNS报文分析

DNS查询和响应的报文格式如下,它由12字节长的首部和4个可变长度字段组成。格式如下:

头部
标识 标志
问题数 资源记录数
授权资源记录数 额外资源记录数
内容字段
查询问题
回答(资源记录数可变)
授权(资源记录数可变)
额外信息(资源记录数可变)

先看一个例子,后面再针对例子说明各个字段的含义:
先打开wireshark,监听dns协议,然后命令行运行 dig www.163.com,此时返回的信息如下:

ssj@ssj-mbp ~/Prog $ dig www.163.com 
; <<>> DiG 9.9.7-P3 <<>> www.163.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 60537
;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 5, ADDITIONAL: 3

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.163.com.           IN  A

;; ANSWER SECTION:
www.163.com.        535 IN  CNAME   www.163.com.lxdns.com.
www.163.com.lxdns.com.  536 IN  CNAME   163.xdwscache.ourglb0.com.
163.xdwscache.ourglb0.com. 38   IN  A   122.13.74.252
163.xdwscache.ourglb0.com. 38   IN  A   157.255.20.6
163.xdwscache.ourglb0.com. 38   IN  A   112.90.246.87

;; AUTHORITY SECTION:
ourglb0.com.        2143    IN  NS  dns4.ourglb0.info.
ourglb0.com.        2143    IN  NS  dns3.ourglb0.org.
ourglb0.com.        2143    IN  NS  dns1.ourglb0.org.
ourglb0.com.        2143    IN  NS  dns2.ourglb0.info.
ourglb0.com.        2143    IN  NS  dns5.ourglb0.org.

;; ADDITIONAL SECTION:
dns1.ourglb0.org.   2493    IN  A   150.138.173.201
dns5.ourglb0.org.   10  IN  A   221.202.204.225

;; Query time: 78 msec
;; SERVER: 10.0.1.13#53(10.0.1.13)
;; WHEN: Sat Aug 05 16:52:20 CST 2017
;; MSG SIZE  rcvd: 306

可以看到DNS请求用的UDP协议封装的,忽略前面的以太网,IP,UDP头部,我们只关注DNS协议的具体数据包内容。DNS协议首部分为标识和标志,问题数,资源记录数,授权资源记录数,额外资源记录数。下面一一分析:

3.1 DNS协议头部

标识:
标识由客户端程序设定并由服务器返回结果,客户端程序通过它来确定响应与查询是否匹配,示例中标识字段为0xb182

标志:
而16bit的标志字段则分为若干子字段如下:

1 4 1 1 1 1 3 4
QR opcode AA TC RD RA Z AD CD rcode

问题数: 请求包为1,响应包为1.

资源记录数: 请求包为0,响应包为5.

授权资源记录数: 请求包为0,响应包为5.

额外资源记录数: 请求包为0,响应包为1.

3.2 DNS协议内容字段

3.2.1 查询内容字段

查询问题

查询问题的每个问题格式如下:查询名,查询类型和查询类。
查询名是 www.163.com 存储格式是 3(计数) w w w 3(计数) 1 6 3 3(计数) c o m
查询类型:在这里是00 01,一个字节,对应类型A。常用的查询类型对应的数值和描述如下:

查询类型 数值 描述
A 1 IP地址
NS 2 名字服务器
CNAME 5 规范名称
PTR 12 指针记录
HINPO 13 主机信息
MX 15 邮件交换记录
AXFR 252 对区域转换的请求
*/ANY 255 对所有记录的请求

查询类:这里是00 01,即对应IN。指互联网地址,通常这个值为1.

额外信息(Additional Data)

额外信息这里有EDNS(扩展DNS)的内容,EDNS允许请求方通知名字服务器返回大的数据包。这种新的资源记录叫OPT(即伪资源记录),OPT不能被缓存和转发,只存储在DNS请求和响应的额外信息段中。注意,用dig的时候在请求中通常会有额外信息这一项,一般的DNS请求没有该项,如果不想在请求中加EDNS,则可以使用dig +noedns xxx.com。EDNS的记录格式如下:

3.2.2 响应内容字段

查询问题

由响应包可知,查询问题部分与查询请求基本一致。

答案

接下来是答案部分,这里一共有5条记录。答案的格式如下:
域名,类型,类,TTL,资源数据长度,资源数据。

;; ANSWER SECTION:
www.163.com.        535 IN  CNAME   www.163.com.lxdns.com.
www.163.com.lxdns.com.  536 IN  CNAME   163.xdwscache.ourglb0.com.
163.xdwscache.ourglb0.com. 38   IN  A   122.13.74.252
163.xdwscache.ourglb0.com. 38   IN  A   157.255.20.6
163.xdwscache.ourglb0.com. 38   IN  A   112.90.246.87

第1条记录为CNAME类型记录。首先是16个字节0xc00c表示域名,这里用的压缩的方式,转换成二进制是0x11000000 00001100即16个字节的前两位为11,这表示它是一个16bit的指针而不是8bit的计数字节,后面的14位说明域名针对标识的偏移位置为12,即为查询问题字段的域名开始位置。接下来的1个字节为记录类型0x05,也就是CNAME类型,然后2个字节是0x0001,即类为IN。接着4字节0x00000111为生存时间TTL为273,接下来2个字节0x0014是资源数据长度为20,后面的20个字节为规范名字www.163.com.lxdns.com,注意最后的com是域名结尾部分,也是用的压缩的方式,即用的前2位标识,后面14位指定偏移位置为20.

第2条记录也是CNAME的。www.163.com.lxdns.com CNAME到163.xdwscache.ourglb0.com

第3条记录为A记录,163.xdwscache.ourglb0.com的一个IP地址为122.90.246.87,TTL为38,数据长度为4字节,数据内容为IP地址。后面的2条记录也全都为163.xdwscache.ourglb0.com域名的A记录。

也就是说 www.163.com的别名是 www.163.com.lxdns.com,而www.163.com.lxdns.com的别名又是 163.xdwscache.ourglb0.com。最终解析163.xdwscache.ourglb0.com域名有5个对应的IP地址。

授权

接着是五条授权服务器记录,如下:

;; AUTHORITY SECTION:
ourglb0.com.        2143    IN  NS  dns4.ourglb0.info.
ourglb0.com.        2143    IN  NS  dns3.ourglb0.org.
ourglb0.com.        2143    IN  NS  dns1.ourglb0.org.
ourglb0.com.        2143    IN  NS  dns2.ourglb0.info.
ourglb0.com.        2143    IN  NS  dns5.ourglb0.org.

分别对应5条授权服务器记录,第1条如下,其他4条类似:

授权服务器知道后,如果我们直接向授权服务器的IP发送dns查询请求,可以看到响应中的AA字段会设置为1,表示该名字服务器是授权于该域的。运行 dig @150.138.173.201 163.xdwscache.ourglb0.com可以看到AA设置为了1.

额外信息

额外信息记录有2条,如下所示,A记录的格式,记录的是授权服务器的ip地址。

;; ADDITIONAL SECTION:
dns1.ourglb0.org.   2493    IN  A   150.138.173.201
dns5.ourglb0.org.   10  IN  A   221.202.204.225

4 指针查询

前面说到的都是正向查询,即根据域名查询IP地址,还有一种查询是指针查询,与域名查询IP相反,由IP地址查询对应的域名。注意到顶级域arpa就是用来做这个的,如果没有arpa顶级域,那么要查询IP地址对应的域名是很麻烦的。使用 dig -x xxx.xxx.xxx.xxx可以发送指针查询来查询一个IP对应的域名。

5 使用dnsmasq搭建DNS代理

在项目中使用到consul做服务发现,而consul本身搭载了一个DNS服务器,我们需要将consul的服务域名如 redis.service.consul的解析指向consul的DNS,而将其他域名解析使用系统本身的DNS。

使用apt-get install dnsmasq安装好dnsmasq后,配置文件/etc/dnsmasq.conf如下设置,另外添加/etc/dnsmasq.d/consul.conf文件,内容为server=/consul/172.17.42.1#8600(其中 172.17.42.1:8600 是consul的DNS服务器监听地址),而/etc/resolv.dnsmasq.conf文件内容跟/etc/resolv.conf一致,里面存储上游DNS服务器列表地址。

###/etc/dnsmasq.conf内容###
resolv-file=/etc/resolv.dnsmasq.conf
interface=eth0
cache-size=10000 #设置缓存大小
conf-dir=/etc/dnsmasq.d/,*.conf
max-cache-ttl=600 #设置最大缓存时间

这样的效果就是,针对consul的域名全部转发到consul的DNS服务器处理,而其他的域名则由resolv.dnsmasq.conf文件中的DNS服务器进行解析。需要注意的一点是,对于转发到consul的域名解析请求,dnsmasq不会做缓存,而通过resolv-file中的DNS服务器解析的请求,则会缓存起来,下次请求只要缓存没有过期就会从缓存中返回。

6 参考资料

上一篇 下一篇

猜你喜欢

热点阅读