DNS域名解析那点事

基础知识

根域

其实就是一个点,我们访问的所有网站,其实最后都是需要以点结尾,如www.baidu.com. 但是如果你真去那么访问的话,是访问不了的。猜测大概是浏览器做了优化。

根域服务器

13个ip地址,分别对应字母.root-servers.net,其中字母从a到m,正好13个。

一个无关紧要的误解 利用技术可以做到这13个IP地址对应全球800+的服务器,但是其实理解成全世界只有13台根域名服务器也无伤大雅

顶级域

顶级域(Top-level Domain,TLD)也叫一级域,包括通用的.com.net 等以及有国家性质的.cn.jp 等,这些域,都会有自己的域名服务器,这些域名服务器通称权威域名服务器。你可能会见过一个特殊的顶级域名arpa,以及一个特殊二级域名in-addr ,而且它们俩总是配套出现,这个涉及到后面的反向解析。

二级域

处于顶级域名之下的域。二级域名是域名的倒数第二个部分,例如在域名example.com中,二级域名是example

多级域名说明

1
2
3
4
5
www.   zhihu.  com     .
三级域 二级域 顶级域 根域

www. zhihu. com. cn .
四级域 三级域 二级域 顶级域 根域

Zone的概念

DNS的一颗子树就可以是一个区域(zone)。而 区域传送的意思是,主服务器把自己的数据通过区域传送的方式给辅DNS服务器。

域名服务器记录

利用阿里云云解析DNS的一张图就很能说明问题:

1564543709961

常用的就是A、CNAME、NS这三个,所以再单独摘出来好好聊聊这三个。

  • A记录。简单来说就是目前大多数人理解的DNS的作用,就是把一个域名转成一个ipv4地址。
  • CNAME记录。别名记录,也就是我如果注册了一个example.com 这个域名,然后我配置了CNAME,指向了百度,那么当你在地址栏输入example.com的时候,地址栏会出现baidu.com,然后打开百度首页。注意如果A和CNAME同时存在,A记录生效,CNAME不生效。
  • NS记录。解析服务器记录。用来指明,由哪台服务器对子域名进行解析。假设目前我购买了example.com 这个二级域名,然后希望由别的DNS服务器进行解析,那就需要在记录值填入那台DNS服务器的域名(不可以写ipv4地址,亲测)。

更多的记录以及详细配置,可见自己的解析商文档,这里提供腾讯云阿里云

DNS相关命令

我这边自己常用的是三个,分别是host dignslookup 这三个。

安装

Fedora / Centos系统 :sudo yum -y install bind-utils

Debian / Ubuntu系统:sudo apt-get -y install dnsutils

host

用法最简单,只需要host+你想要查询的即可。这个查询的既可以是ip地址,也可以是域名

例如host www.baidu.com会输出:

1
2
3
www.baidu.com is an alias for www.a.shifen.com.
www.a.shifen.com is an alias for www.wshifen.com.
www.wshifen.com has address 103.235.46.39

例如host 114.114.114.114会输出:

1
114.114.114.114.in-addr.arpa domain name pointer public1.114dns.com.

nslookup

这个命令在windows下也有喔。这个命令最基础的用法和host一样,都是后面接你想查的内容即可。但是如果要指定DNS服务器进行查询的话,用它会比较方便。

nslookup www.baidu.com 127.0.0.1 让本机的DNS服务器解析百度网页(前提是你本机得有DNS服务器,否则是无法解析的)。

当然你还可以直接输入nslookup 进入交互模式,然后根据你自己需要的进行交互即可。

dig

这个命令是最有用的,稍微详细的解析下:

1564732561813

使用了dig解析了一下baidu这个域名,然后简单分成了四部分。

  • 第一部分,主要是dig这个软件的信息,以及它收到的DNS服务器返回的数据包的信息,opcode是操作码,QUERY,代表是查询操作;status 状态,NOERROR,代表没有错误;id是用来标识数据包的。(询问包和应答包的id是需要一样的);flags比较复杂:

    • qr query,查询标志,代表是查询操作
    • rd recursion desired, 代表希望进行递归(recursive)查询操作
    • ra recursive available 在返回中设置,代表查询的服务器支持递归(recursive)查询操作。
    • aa Authoritative Answer 权威回复,如果查询结果由管理域名的域名服务器而不是缓存服务器提供的,则称为权威回复。

    接下来是四项:

    • QUERY 查询数,1代表1个查询,对应下面的QUESTION SECTION中的记录数
    • ANSWER 结果数,2代表有2项结果,对应下面ANSWER SECTION中的记录数
    • AUTHORITY 权威域名服务器记录数,0代表该域名有0个权威域名服务器,可供域名解析用。
    • ADDITIONAL 格外记录数,1代表有1项格外记录。
  • 第二部分一开始的OPT PSEUDOSECTION没看懂。接下来就是你询问信息。

  • 第三部分是就是给出的答案,我以前一直不知道IN代表的是什么,其实是INternet的意思….当然现在这个环境下应该也只有IN的记录了吧。

  • 第四部分英语一般的同学都能懂吧。

实际使用中还有以下比较常用的选项,在这里记录下:

  • @想要让哪个服务器来解析,例如:dig www.baidu.com @127.0.0.1 本机解析百度的域名

  • +trace选项 dig www.baidu.com +trace 从根域名服务器开始解析。如果同时设置了@指定查询的服务器,只会影响一开始去寻找根域名服务器。

一次DNS解析过程

首先需要知道,DNS服务器,可能架设在你的内网中,也可能架设在公网中。在linux下利用cat /etc/resolv.conf 以及win下ipconfig /all 可以查询自己的dns服务器,然后根据ip地址来判断。

使用的是Ubuntu 16.04,直接使用命令dig +trace www.baidu.com 即可追踪是如何解析的。

1564541540665

可以看到,第一步是向13台根域名服务器去询问。


1564542214848

可以从图中看出,13台根服务器中的一台(字母为a的这台)给了我们13个顶级域名服务器的地址,告诉我们,.com相关的请去问 务器。到这里,根域名服务器就完成了它的使命,它的使命非常的简单,仅仅需要告诉你,顶级域名对应的顶级域名服务器是哪些。比如我问xxx.xxx.xxx.cn这个地址,去向根域名服务器问,它只会告诉你.cn会在哪些顶级域名服务器中找到,仅此而已。其实每台根域名服务器上仅仅存了一个大小约2M的文件(进入ftp://rs.internic.net/domain/ ,找到一个叫root.zone的文件,对就是它!下下来你会发现一些有意思的顶级域名),通过这个文件查询一下就可以了。


好,到现在已经知道了.com顶级域名服务器的地址了,接下来该去问字母.gtld-servers.net 关于二级域名的信息了。

1564542856921

可以从上图中看到,去询问了b.gtld-servers.net这个顶级域名服务器,然后它告诉我们,去ns2.baidu.com. 等服务器上继续问吧。


1564543070778

可以看到最后选择了ns3这台服务器,然后问到了最后的结果。大致过程就是这样。

DNS的报文格式

自己抓了本机的两个包,分别是询问和回答,然后对着这两个包进行解析

DNS询问包

1564735550174

  • Transaction ID。16位,用来标识这个包,服务器如果响应了这个包,这个序列号也必须一样。
  • Flags,也是16位。第一位是用来表明这个包是询问(0)还是回答(1)。接下来4位是Opcode,分别有0000(标准查询),0001(反向查询),0010(服务器状态请求)。注意,空一位!! 接下来是Truncated,上图中是不允许截断。如果是1则说明在使用UDP的时候如果超了512字节就只返回前面的512字节。RD标志位,置为1的时候说明希望服务器能够递归查找。注意又空了一位!! 然后是一个保留位,和一个不接受非权威数据的置位。 这部分可能近些年来做了修改,在TCP/IP详解的卷一中有点出入。
  • 接下来的16位是问题数,16位回答数,16位权威回答数,16位额外资源数。(从现在看来,压根不需要每个都16位那么多吧?)
  • 最后就是询问的问题,上图中问的是一个GitHub的ip。

DNS应答包

1564736070525

可以看到确实符合之前所说的各项要求,而且wireshark也直接帮忙做了解析,清楚简单。

配置自己的域名服务器

很多人购买了域名,例如我就购买了一个chenlangping.cn的域名,买了这个域名之后,相当于之后的三级域名、四级域名都是我的了,可以任我自己解析。现在比较方便的做法是,直接去找购买域名的服务商,一般来说他们肯定会提供云解析DNS服务,然后在上面添加记录就行了。但是我这人比较喜欢折腾,就自己去配置了一个DNS服务器,这样以后诸如aaa.chenlangping.cn这种网址就可以由我自己来解析了。

使用软件

BIND9 (Berkeley Internet Name Domain)为什么使用它?根域名服务器都用它你不用它? Bind 是一款开源的 DNS 服务器软件,由美国加州大学 Berkeley 分校开发和维护的,按照 ISC 的调查报告,BIND 是世界上使用最多最广泛的域名服务系统。

接下来使用Ubuntu 16.04作为说明,现在我已经有了chenlangping.cn 这个域名,然后希望aaa.chenlangping.cn这个域名由我的服务器上面的DNS服务器来进行解析。

前排提醒:

1567999954871

基本就相当于你的DNS不能解析到国内的服务器,所以在下面的例子中需要填写到国外的服务器,或者指定查询的DNS服务器为本机这样才能进行测试。

下载安装:

apt-get install bind9

主要配置文件在/etc/bind 文件中

1
2
3
4
5
6
7
8
9
10
11
12
13
├── bind.keys
├── db.0
├── db.127
├── db.255
├── db.empty
├── db.local
├── db.root
├── named.conf
├── named.conf.default-zones
├── named.conf.local
├── named.conf.options
├── rndc.key
└── zones.rfc1918
  • db开头的那些文件是记录文件,也就是你的A记录啊,NS记录啊,CNAME记录什么的就要写到这些文件中。
  • named开头的那些是配置文件。其中named.conf其中是三个include,相当于把另外三个包含进去了,所以其实你的配置内容写到哪个都行,但是为了好管理,还是严格按照官方推荐的写。
  • 其余的可以不用理会。

首先编辑named.conf.default-zones ,在其中追加以下内容:

1
2
3
4
zone "chenlangping.cn" {
type master;
file "/etc/bind/db.chenlangping.cn";
};

内容很好理解,就是对于chenlangping.cn这个域,是主DNS服务器,然后具体配置文件是/etc/bind/db.chenlangping.cn

顺着这个思路,我们需要到/etc/bind下创建一个叫db.chenlangping.cn的文件并进行编辑,但是推荐直接复制db.local作为模板,方便修改。以下是具体的文件内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
;
; BIND data file for local loopback interface
;
$TTL 604800
@ IN SOA chenlangping.cn. root.localhost. (
2 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS localhost.
aaa IN A 77.77.77.77

首先注意一下第五行,记得修改成你的域。最后就是你需要增加的记录了,这里的IP地址是我瞎写的。配置完了重启一下bind的服务 service bind9 restart ,然后到你的云DNS解析服务商那里,添加一下记录:

1564834275304

这里我遇到一件超级坑爹的事情。从上图中(上图是正确的配置)发现,其实aaa.chenlangping.cn是交给dns.chenlangping.cn这个域名服务器进行解析的,而dns.chenlangping.cn这个域名其实就是我的服务器公网IP,所以我当时其实直接是把aaa.chenlangping.cn的记录那里写的是公网ip,当时还觉得这样可以省去查找dns.chenlangping.cn的ip地址,结果就是根本解析不了aaa.chenlangping.cn这个网址了!最后查阅资料发现了原因,引用如下:

MX, CNAME, PTR, and NS records point to hostnames. A records point to IP addresses.

Putting an IP address in an NS record is a pretty common DNS misconfiguration. One reason is that you might have NS records pointing to servers outside of your domain for someone doing secondary DNS for you. That remote domain might change the IP address of the server (but leave the hostname alone).

解决完问题就可以通过nslookup aaa.chenlangping.cn 或者dig aaa.chenlangping.cn 就可以看到结果了。

反向解析

如果你只是希望能够了解简单的DNS,那到这里就可以了,接下来是DNS中虽然很重要但是其实理不理解也无所谓的——从IP到域名的解析。

日后再来补吧,感觉目前不重要。

排错相关

首先我在我的服务器上搭了Bind9的DNS服务器,然后发现解析不了,可以通过以下参考案例进行排错:

tcpdump抓包

tcpdump port 53 指定抓取53端口的包。然后我运行了ping www.baidu.com,得到了下面的结果

1
2
3
4
17:24:31.083843 IP 我的服务器的ip地址.55216 > dns.google.domain: 36715+ [1au] A? www.baidu.com. (42)
17:24:31.084022 IP 我的服务器的ip地址.55216 > dns.google.domain: 15226+ [1au] AAAA? www.baidu.com. (42)
17:24:31.122133 IP dns.google.domain > 我的服务器的ip地址.55216: 36715 3/0/1 CNAME www.a.shifen.com., CNAME www.wshifen.com., A 103.235.46.39 (111)
17:24:31.148289 IP dns.google.domain > 我的服务器的ip地址.55216: 15226 1/1/1 CNAME www.a.shifen.com. (126)

可以看到本机的55216端口向谷歌的DNS服务器发送了一个ID为36715的询问报文,其中的+代表希望谷歌的DNS服务器能够递归给答案,A代表ipv4地址,问号代表这是一个询问报文。回答报文中的3/0/1分别表示的是回答数/权威回答/附加信息,其他的应该就好理解了。

善用dig的一级一级查询

配置好了自己的DNS服务器发现解析不了?不如试试先用dig +trace来解析下你的域名,观察一下一级一级下来能否查询到你的记录,如果不能,那就看看是哪一层有问题。如果能,反而头大。我之前NS写了ipv4的地址,然后发现dig +trace能够最后查到我在自己的DNS服务器上写的记录的,但是用别的host之类的却解析不了。原因么我觉得可能是dig比较智能,看到NS是ipv4的记录也会继续追踪下去,DNS服务器则不会继续。

所以,第一步,确定下你的DNS服务器配置是正确的,可以通过dig @127.0.0.1 example.com 观察本机是否正确解析来判断。之后就需要你一步一步往上进行排查了。如果发现都没问题,但是是服务器收不到包的,可以考虑下防火墙,或者阿里云有自己的安全策略,需要自己去配置放行53端口才可以。