Linux系统下搭建DNS服务器——DNS原理总结

  • DNS原理
  • 域名到IP地址的解析过程
  • IP地址到域名的反向域名解析过程
  • 抓包分析DNS报文和具体解析过程
  • DNS服务器搭建和配置

这个东东也是今年博主参见校招的时候被很多公司问过的,虽然理论性比较强,但是作为一个程序员,个人认为熟悉DNS是非常重要的,要理解它并能帮助解决一些实际问题。

面试实录

  • 打开一个URL,在网络层面都发生了哪些事情?(当中说到了DNS原理,这个是绕不过的)
  • 用过 Linux 么?你用它平时都做什么事情啊?(首先是在该环境下写代码,搭建过一些集群,当然还有一些服务器的搭建,比如本文内容)
  • DNS 是基于 TCP 还是 UDP 的?端口号是多少?
  • 具体忘了,说到了负载均衡的请求分发(聊了DNS的分发功能)
  • 什么是DNS劫持?

虽然当时回答了,但是还是感觉得系统总结下,备忘。

DNS原理和理解

DNS的本质是什么?

Domain Name System = DNS(域名系统)其实是一个数据库,是用于 TCP/IP 程序的分布式数据库,同时也是一种重要的网络协议。DNS储存了网络中的 IP 地址与对应主机的信息,邮件路由信息和其他网络应用方面的信息,用户通过询问解决库(解决库发送询问并对DNS回应进行说明)在 DNS 上查询信息。

DNS的作用是什么?

DNS是网络分层里的应用层协议,事实上他是为其他应用层协议工作的,简单说就是把域名,或者说主机名转化为IP地址(同时也提供反向域名查询的功能),类似字典,比如访问 ,实际访问的是它的IP地址,因为机器识别的是拥有固定格式和含义的IP地址,而域名可以千奇百怪,甚至是中文,不利于识别。还有比如公司内部的域验证,通过分配给员工的域账号登录内网就必须通过DNS来找到域名权限服务器,来认证身份,故有些书上说:DNS是因特网世界里不可缺少的东西。

比如,使用host命令进行DNS查询

host命令用来做DNS查询。如果命令参数是域名,命令会输出关联的IP;如果命令参数是IP,命令则输出关联的域名。

 

Linux系统下搭建DNS服务器——DNS原理总结

 

为什么叫域名系统,什么是域名?

人和人要互相识别和记忆,需要名字作为辅助,而对于网络世界,在因特网内也需要一种命名系统来做类似的事情,该系统使用了域来划分,任何一个网络里的主机(或者路由器)都有独一无二的域名(类似国家代码),域又能继续划分为子域(类似每个国家有不同的省份代码),子域还能继续划分(每个省都有自己的各个城市的代码)……在因特网内对应的就是*域名(com,net,cn,org等),二级域名……注意这仅仅是一种逻辑的划分。而这些域名系统在形式上组成了一种树结构。

 

Linux系统下搭建DNS服务器——DNS原理总结

 

名字(也叫标号)组成只能是英文或者数字,目前中文也支持了,长度不大于63个字符,总共完整域名长度不超过255个字符,英文域名不区分大小写,从右到左,域名级别依次降低。www是表示万维网,不属于域名。

域名空间树结构

 

Linux系统下搭建DNS服务器——DNS原理总结

 

域名的名字空间是一个树结构,根没有名字,各个树叶是单台计算机名,不能继续划分。

域名服务器

DNS服务器管理范围的单位是区,不是域,因为区才是DNS服务器管理的实际范围,区是域的子集,同一个区里的主机节点必须互通,它们都有一个统一的访问权限,该访问权限在通过一个权限域名服务器管理。比如,公司a,有两个部门x,y,部门x又有两个分部q和r,a会设立一个区叫(区和域可以同名),这是一个大的权限范围,然后下属再设立一个区,叫,那么区都属于域

 

Linux系统下搭建DNS服务器——DNS原理总结

 

DNS服务器也是类似域名空间树一样的树结构,依次分为根域名服务器(知道所有的*域名服务器的域名和IP,最重要,它要是瘫痪,整个DNS就完蛋),然后是*域名服务器(管理二级域名),其次是权限域名服务器(负责区的域名服务器)。

最后是本地域名服务器(也叫默认域名服务器),本地域名服务器离主机很近(书上说不超过几个路由器),速度很快,其实本地域名服务器本质不属于域名服务器架构。

如图就是Linux的本地域名服务器配置

 

Linux系统下搭建DNS服务器——DNS原理总结

 

如图是Windows下本地DNS服务器配置

 

Linux系统下搭建DNS服务器——DNS原理总结

 

分布式域名系统

因为因特网规模很大,所以整个因特网只使用一个域名服务器是不行的。为了可靠,使用了分布式的域名系统,即使单个计算机除了故障,也不会妨碍整个DNS系统的正常运行。并采用c/s方式。DNS使大多数名字都在本地解析(resolve),仅有少量解析需要在因特网上通信,因此分布式DNS系统借助分布式的主机备份和缓存机制,非常强壮和有足够的性能。

DNS劫持及解决办法

DNS劫持又称域名劫持,说白了就是当用户请求DNS解析的时候,对正常的DNS请求报文进行拦截,偷到请求的域名,然后就可以做手脚,比如常常遇到访问某个健康的网址的时候,明明输入的网址是,结果却跳转到了不可描述的网站……即把审查范围,或者权限范围以外的请求放行,否则返回假的IP地址或者什么都不做使请求失去响应,效果就是让人误以为断网(360网络诊断里经常说的,打的开QQ,但是无法浏览网页的现象),或者得到了假网址,黑客们经常利用漏洞或者程序的缺陷对用户的DNS进行篡改,进行钓鱼网站的欺诈活动。

解决办法可以手动修改本地DNS域名服务器地址,首选DNS服务器:114.114.114.114,是国内第一个、全球第三个开放的DNS服务地址,又称114DNS,或8.8.8.8(google提供的DNS服务器)等,然后修改宽带密码,路由器密码,主机密码。

域名到IP地址的解析过程

当一个应用需要把主机名解析为IP地址时,该应用进程就调用地址解析程序,它自己就变为了DNS的一个客户,把待解析的域名放在DNS请求报文中,以UDP方式先发给本地域名服务器,本地域名服务器在查找域名后,把对应的IP地址放在回答报文中返回,应用程序获得目的主机的IP地址后即可进行通信。若本地域名服务器不能回答该请求,则此域名服务器就暂时称为DNS的另一个客户,并向其他域名服务器发出查询请求。这种过程直至找到能够回答该请求的域名服务器为止。

域名的解析过程

主机向本地域名服务器的查询一般都是采用递归查询

 

Linux系统下搭建DNS服务器——DNS原理总结

 

如果主机所询问的本地域名服务器不知道被查询的域名的IP地址,那么本地域名服务器就以DNS客户端的身份(递归思想),向根域名服务器继续发出查询报文(替主机查询),不让主机自己进行查询。递归查询返回的结果或者是IP,或者报错。这是从上到下的递归查询过程。

本地域名服务器向根域名服务器查询一般采用迭代查询

当根域名服务器收到本地域名服务器的查询请求,要么给出ip,要么通知本地域名服务器下一步应该去请求哪一个*域名服务器查询(并告知本地域名服务器自己知道的*域名的IP),让本地域名服务器继续查询,而不是替他查询。同理,*域名服务器无法返回IP的时候,也会通知本地域名服务器下一步向谁查询(查询哪一个权限域名服务器)……这是一个迭代过程。

 

Linux系统下搭建DNS服务器——DNS原理总结

 

到底采用哪种查询,取决于原始查询报文的设置,不绝对。

DNS缓存

DNS中使用了高速缓存,因为域名到地址的映射不常变,故为提高效率而设,主机在启动时从本地服务器下载名和地址的全部数据,并维护存放自己最近使用的域名的缓存,并且只在从缓存中找不到名字时才使用根域名服务器发起查询。实际中,当一个 DNS 服务器接收到一个 DNS 回答后,会将其信息缓存一段时间,当再有一个对相同域名的查询时,便可直接回复。通过 DNS 缓存,大部分查询都只需要本地 DNS 服务器便可完成解析。

DNS缓存污染

本地域名服务器在接收到DNS请求时,先查找DNS缓存,如果缓存命中直接返回结果,如果黑客攻入路由器,对部分域名的缓存进行了更改,比如将缓存的结果指向不可描述的页面,那么即导致用户的正常请求被转移……,此时可以清除各级缓存(浏览器,系统,路由器,DNS缓存)。貌似无法避免,只能是提高安全意识,即使使用了 HTTPS也不行,因为DNS解析过程发生在HTTPS请求交互前。

FQ方法之——hosts 文件

Hosts是一个没有扩展名的系统文件,作用是将一些常用的网址域名与其对应的IP地址建立一个关联“数据库”, 其实 hosts 文件可以看作是一个小型的本地 DNS 服务器。

 

Linux系统下搭建DNS服务器——DNS原理总结

 

实际上网时域名的解析过程

优先顺序是:当用户在地址栏输入一个URL之后,浏览器首先查询浏览器的缓存,找不到就去查询Hosts文件和本地DNS缓存,如果hosts和本地DNS缓存都没有找到域名对应的IP,则自动进入路由器的缓存中检查,以上均为客服端DNS缓存,若在客户端DNS缓存还是没找到,则进入ISP DNS缓存中查询,还是找不到,最终才向 根DNS 服务器发出 DNS 查询报文,再找不到就报错……

IP地址到域名的反向域名查询

先了解下DNS报文,稍后会分析

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

哎,这个报文格式和名字也是醉了,不过不碍事,当在浏览器内输入URL时,便开始了DNS解析过程,最后会把找到后的IP地址告知浏览器客户端,方便它继续发出 HTTP(s)请求,该过程中,浏览器提出的查询记录类型叫A记录(address)查询,其他查询记录类型常见的有A(地址)记录、CNAME(别名)记录、MX(邮件交换)记录等。

比如问:的A记录是什么?

是 220.181.110.181

这个A记录意思是从域名解析得到IP地址。那么反过来,从IP地址得到域名的解析过程也需要一个记录,叫PTR记录(和A记录功能相反),可以使用nslookup命令查询,可以通过查询IP地址的PTR记录来得到该IP地址指向的域名,达到反查的目的。

反向域名查询和垃圾邮件过滤

IP反向解析主要应用到邮件服务器中来阻拦垃圾邮件,比如用 xxx@xxx.com 给邮箱 xxxxx@qq.com 发了一封信。qq邮件服务器会查看信头文件,信头文件显示信是由哪个IP地址发出的,然后根据IP地址反向解析,如反向解析到这个IP所对应的域名是 (不在黑名单)那么就接受,否则拒绝。

了解反向域名-arpa

域名系统中,一个IP地址可对应多个域名,在Internet上是不会去傻傻的遍历整个域名树的。故DNS的*域名提供了一个特别的*域——arpa 用来做反向域名解析,也称为反向域名。当一个主机加入网络,获得DNS授权,它的IP地址假设为192.168.1.1,它也顺便获得了对应IP地址的 in-addr.arpa (逆向解析域in-addr.arpa)空间的授权,注意DNS名由树底部向上组织,故它的DNS名字为192.168 .1.1.in-addr.arpa。IP地址的第一字节一定位于in-addr的下一级。这样欲解析的IP地址就会被表达成一种像域名一样的形式,后缀以反向解析域名"in-addr.arpa"结尾。

 

Linux系统下搭建DNS服务器——DNS原理总结


本质上:反向域名解析是将IP地址表达成了一个域名,这样反向解析的很大部分可以纳入正向解析中。

抓包分析具体解析过程

 

Linux系统下搭建DNS服务器——DNS原理总结

 

如上是通常情况下的DNS报文,基于UDP数据报封装(同时DNS也支持TCP),并且要知道DNS服务器的默认端口是53

ping一个主机,开始抓包

 

Linux系统下搭建DNS服务器——DNS原理总结

 

观察出现的数据包

 

Linux系统下搭建DNS服务器——DNS原理总结

 

如图,第一行是DNS查询报文,第二行是DNS回答报文。

先看整个数据包的结构

 

Linux系统下搭建DNS服务器——DNS原理总结

 

证实了DNS确实为应用层的协议,目的端口号确实是53,传输层一般情况下采用UDP也是ok的,网络层是IP协议,数据链路层有以太网帧。

查看DNS数据包

 

Linux系统下搭建DNS服务器——DNS原理总结

 

对应的抽象报文格式图

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

先看查询报文头

 

Linux系统下搭建DNS服务器——DNS原理总结

 

首部12字节

 

Linux系统下搭建DNS服务器——DNS原理总结

 

标识ID,两个字节,对应DNS查询和DNS响应报文的id,目的是可以辨别DNS应答报文是哪个请求报文的响应,如下是响应报文的ID,两个一样

 

Linux系统下搭建DNS服务器——DNS原理总结

 

标志flags(不同于标识)字段又单独划分了

 

Linux系统下搭建DNS服务器——DNS原理总结

从左到右为:QR,操作代码op,AA,TC,RD,RA,Z,响应代码

QR(query,response)1位,0代表查询,1代表响应

操作代码4位,0代表标准查询,1代表反向查询

AA(authoritative answer)1位,如果响应数据报设定,说明响应是由域内权限域名服务器发出

TC(truncation)1位,1代表报文被截断,如果DNS响应报文超过了512字节,只返回这512个字节,0代表没有截断

RD(recursion desired)1位,递归期望,请求报文设定,在响应报文返回,1代表名字服务器必须递归处理该查询。如

果该位为0,且被请求的名字服务器没有一个授权回答,它就返回一个能解答该查询的其他名字服务器列表,也就是迭代查询。

RA(recurision  available)1位,递归可用,响应报文设定,说明域名服务器支持递归查询

Z代表保留字,3位。必须为0

响应码是4位,类似HTTP响应码
- 无差错
- 格式错误
- 域名服务器出现错误
- 域参照问题
- 查询类型不支持
- 被禁止
~ 15 保留

然后是查询的问题数

 

Linux系统下搭建DNS服务器——DNS原理总结

Quetions(问题数) ,通常为1。Answer RRs(资源记录数),Authority RRs(授权资源记录数),Additional RRs(额外资源记录数)通常都为0。

以上是12字节的DNS包头

然后是DNS的报文身体部分(问题or回答部分)

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

Queries为查询或者响应的正文,如下是请求报文里的问题部分

 

Linux系统下搭建DNS服务器——DNS原理总结

 

每个问题对应一个查询类型,响应报文里的资源记录部分里每个响应(资源记录)也对应一个资源类型。PS:资源记录也叫响应,如下

 

Linux系统下搭建DNS服务器——DNS原理总结

分为 Name Type Class

Name(查询名称):域名 
Type(查询类型):2字节,这里是A记录.
Class类,2字节,IN表示Internet数据,一般为1

大约有20多种查询记录类型,最常用的查询类型是A记录类型,例子里DNS查询报文查询A记录,从域名www.baiodu.com解析到IP地址,PTR记录类型(反向查询IP地址的PTR记录,也叫指针记录),CNAME记录类型等。

其中cname就是别名,一般用在SEO中,可以使得多个域名指向同一个IP地址。

还有NS记录,也就是名字服务器name server

下面看DNS响应报文

 

Linux系统下搭建DNS服务器——DNS原理总结

 

大体和查询报文一致,响应包就是多出了一个Answers字段

 

Linux系统下搭建DNS服务器——DNS原理总结

 

响应报文的answer字段,第一个是请求的域名,然后cname记录表示出别名为www.a.shifen.com,这个别名的地址看下面具体的回答

 

Linux系统下搭建DNS服务器——DNS原理总结

Answers字段每项为一个资源记录
除了上面提到过的Name,Type,Class之外,还有Time to Live,Data length,addr

Time to Live(生存时间TTL):表示该资源记录的生命周期,从取出记录到抹掉DNS记录缓存的时间,以秒为单位 

Data length(资源数据长度):以字节为单位

Addr:返回的查询结果 ip地址

DNS使用的网络层协议

DNS同时支持UDP和TCP访问,当名字解析器发出一个查询请求,并且返回响应报文中的TC位设置为1时,名字解析器通常使用TCP重发原来的查询请求,TCP能将用户的数据流分为一些报文段,用多个报文段来传送任意长度的用户数据,即允许返回的响应超过512个字节。

此外,为了减轻单台DNS服务器的负载,有时要将同一DNS区域的内容保存在多个DNS服务器中(主从备份,分布式存储),这时,就要用到DNS的“区域传输”功能。在分布式的DNS数据库中,当一个域的辅助名字服务器在启动时,将从该域的主名字服务器执行区域传送。辅助服务器将定时(通常是3小时)向主服务器进行查询以便了解主服务器数据是否发生变动,如果有变动,为了数据一致性,将执行一次区域传送,区域传送将使用TCP,因为传送的数据远比一个查询或响应多。

故DNS主要使用UDP,TCP为辅,如果是UDP,那么无论是名字解析器还是名字服务器都必须自己处理超时和重传。此外,DNS不像其他的使用UDP的应用一样,大部分操作集中在局域网上,DNS查询和响应通常经过广域网。分组丢失率和往返时间的不确定性在广域网上比局域网上更大。这样对于DNS客户程序,一个好的重传和超时程序就显得更重要。

DNS熟知的端口号

DNS服务器使用的熟知端口号无论对UDP还是TCP都是53

本地私有 DNS 服务器搭建

BIND (Berkeley Internet Name Domain)是DNS协议的一个实现,提供了DNS主要功能的开放实现,包括

  • 域名服务器 (named)
  • DNS 解析库函数
  • DNS 服务器运行调试所用的工具

Bind 是一款开源的 DNS 服务器软件,由美国加州大学 Berkeley 分校开发和维护的,按照 ISC 的调查报告,BIND 是世界上使用最多最广泛的域名服务系统,通过搭建私有的 DNS 服务器,可以把国外的一些不可描述的 ip 地址放到自己的 DNS 服务器中畅快浏览。

安装环境本地ubuntu,客户端和服务器都是使用的一台机器

安装配置BIND

########安装BIND软件
sudo apt-get install bind9 bind9utils bind9-doc

########设置 BIND 为 IPv4 Mode,把 "-4" 添加到 OPTIONS 变量
dashuai@ubuntu:/etc$ sudo vim /etc/default/bind9

########如下
# run resolvconf?
RESOLVCONF=no

# startup options for the server
OPTIONS="-4 -u bind"

########解决只读问题
####1、确认文件属于自己
####2、权限为可读可写
####3、如果还是不行,就sudo vim ……打开即可

配置 DNS 主服务器(最好是设置主备)

########查看本机IP,保证ping通
192.168.124.8

########编辑BIND软件的配置文件 来配置环境
####配置ACL
##添加一个新的 ACL 块,把内网 ip 添加到信任名单,意思是只允许它查询 DNS 服务器 ,提高安全性。

dashuai@ubuntu:/etc/bind$ sudo vim named.conf.options

##如下
acl "trusted" {
    192.168.124.8;  # ns1 只有信任的主机才能查询 DNS 服务器,其他主机不能。
};
        recursion yes;
        allow-recursion {
            trusted;
        };
        listen-on {192.168.124.8};
        allow-transfer {none;};
        
        forwarders {
                114.114.114.114;
        };

##添加解析域
dashuai@ubuntu:/etc/bind$ sudo mkdir zones

####添加正向解析和反向解析文件的位置参数
dashuai@ubuntu:/etc/bind$ sudo vim named.conf.local 

##如下
zone "dashuaiBlog.com" {
    type master;
    file "/etc/bind/zones/db.dashuaiBlog.com";
};

zone "168.192.in-addr.arpa" {
    type master;
    file "/etc/bind/zones/db.192.168";  
};

####在解析域里编写正向解析域文件
dashuai@ubuntu:/etc/bind$ cd zones/
dashuai@ubuntu:/etc/bind/zones$ ls
dashuai@ubuntu:/etc/bind/zones$ touch db.dashuaiBlog.com
touch: cannot touch ‘db.dashuaiBlog.com’: Permission denied
dashuai@ubuntu:/etc/bind/zones$ sudo touch db.dashuaiBlog.com
dashuai@ubuntu:/etc/bind/zones$ ll
total 8
drwxr-sr-x 2 root bind 4096  1月 14 16:50 ./
drwxr-sr-x 3 root bind 4096  1月 14 16:41 ../
-rw-r--r-- 1 root bind    0  1月 14 16:50 db.dashuaiBlog.com
dashuai@ubuntu:/etc/bind/zones$ sudo vim db.dashuaiBlog.com 

##如下
;
; BIND data file for local loopback interface
$TTL    604800
@       IN      SOA     ns1.dashuaiBlog.com. admin.dashuaiBlog.com. (
      ; Serial
    ; Refresh
    ; Retry
    ; Expire
)   ; Negative Cache TTL
;
;
; name servers - NS records
     IN      NS      ns1.dashuaiBlog.com.
; name servers - A records
ns1.dashuaiBlog.com.          IN      A       192.168.124.8     

host1.dashuaiBlog.com.        IN      A      192.168.124.8

####编写反向解析域文件
dashuai@ubuntu:/etc/bind/zones$ sudo vim db.192.168  

##如下
$TTL    604800
@       IN      SOA     dashuaiBlog.com. admin.dashuaiBlog.com. (
        ; Serial
        ; Refresh
        ; Retry
        ; Expire
)       ; Negative Cache TTL
; name servers
      IN      NS      ns1.dashuaiBlog.com.

; PTR Records
2.42   IN      PTR     ns1.dashuaiBlog.com.    ; 192.168.124.8
1.42   IN      PTR     host1.dashuaiBlog.com.  ; 192.168.124.8

服务器环境测试

########检验 BIND  配置文件有没有语法错误
dashuai@ubuntu:/etc/bind/zones$ sudo named-checkconf
dashuai@ubuntu:/etc/bind/zones$ 

########查看正向解析和反向解析文件编写语法是否正确。
dashuai@ubuntu:/etc/bind/zones$ sudo named-checkzone dashuaiBlog.com db.dashuaiBlog.com
zone dashuaiBlog.com/IN: loaded serial 3
OK
dashuai@ubuntu:/etc/bind/zones$ sudo named-checkzone 168.192.in-addr.arpa db.192.168
zone 168.192.in-addr.arpa/IN: loaded serial 3
OK

重启 BIND

dashuai@ubuntu:/etc/bind/zones$ sudo service bind9 restart
 * Stopping domain name service... bind9
waiting for pid 4106 to die
   ...done.
 * Starting domain name service... bind9
   ...done.

配置 DNS 客户端

找一台机器作为DNS客户端,将客户端的 DNS 修改为刚刚搭建的DNS服务器的 ip 地址

########这是修改的本地DNS配置的真实文件
sudo vim /etc/resolvconf/resolv.conf.d/head
####如下
nameserver 192.168.124.8

########修改本地DNS配置文件的link
sudo vim /etc/resolv.conf
####如下
options timeout:1 attempts:1 rotate
nameserver  192.168.124.8

########运行 resolvconf 更新
sudo resolvconf -u

使用nslookup验证

使用nslookup来查询服务器(若使用其他的客户端, ip 地址 需要加入到 "trusted" ACL 里面)。

dashuai@ubuntu:~$ nslookup dashuaiBlog.com
Server:         192.168.124.8
Address:        192.168.124.8#53

Non-authoritative answer:
Name:   dashuaiBlog.com
Address: 192.168.124.8

dashuai@ubuntu:~$ nslookup 192.168.124.8
Server:         192.168.124.8
Address:        192.168.124.8#53

Non-authoritative answer:
8.124.168.192.in-addr.arpa      name = host1.dashuaiBlog.com

Linux系统下搭建DNS服务器——DNS原理总结

上一篇:浏览器 CSS 兼容写法的测试总结


下一篇:wince中对ini文件的操作