1 DNS是什么

DNS(Domain Name System)是互联网的一个重要组成部分,它的主要功能是进行域名管理并且实现域名IP地址的相互转换。在TCP/IP网络模型(也就是当今互联网)中,IP层是通过32位的IP地址(ipv4)进行通信的,而不是域名,域名是方便人类记忆的一种形式,而且在人类和IP地址之间增加一层域名接口,可以增加灵活性,比如一个网站从服务器A搬到了B,你访问的依然是同一个网址,不用关心它实际的服务器地址发生了变化(当然域名只是网址的一部分)。

DNS的数据存储在世界各地的服务器中,每一个可以联网的程序,都有一个DNS解析器,它可以理解为一个功能函数,当你用域名进行通信时,程序会先把域名发送给解析器,等它返回IP地址后再传递给传输层。

2 DNS解析器是什么

只要可以实现域名和IP地址转化的功能模块,我们都可以称为DNS解析器,它通过查找本地缓存或者查询外部的DNS服务器实现这个功能。程序中有解析器,操作系统中也有解析器,程序的解析器本质上依赖的还是操作系统的解析功能。

比如一个用Java写的程序,在编写的时候不用显式调用解析器功能,JDK都封装好了,只需要用域名进行连接就行,JDK会完成解析过程。

简单看一下JDK源码的实现,略过查找缓存等,在InetAddress这个类中,有一个内部静态类PlatformNameService,它的作用是进行域名和IP地址的转换,从注释中可以看到其功能实现是依赖操作系统的。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
/**
    * The default NameService implementation, which delegates to the underlying
    * OS network libraries to resolve host address mappings.
    *
    * @since 9
    */
private static final class PlatformNameService implements NameService {

    public InetAddress[] lookupAllHostAddr(String host)
        throws UnknownHostException
    {
        return impl.lookupAllHostAddr(host);
    }

    public String getHostByAddr(byte[] addr)
        throws UnknownHostException
    {
        return impl.getHostByAddr(addr);
    }
}

impl表示InetAddressImpl这个接口,而这个接口有2个实现,Inet4AddressImplInet6AddressImpl,看一下ipv4的实现:

依赖操作系统内部方法

可以看到最终就是调用的系统内部的方法

3 DNS服务器和域名管理

上面提到,所有的数据都是存在DNS服务器中,那么这些服务器都在哪里呢?

这跟域名管理的方式有关,域名是按层次组织管理的,像.com,.org,.cn这种都是顶级域名,他们都必须具备自己的DNS服务器(至少是一主一从的配置),顶级域名的管理都是由ICANN(Internet Corporation for Assigned Names and Numbers)委托的,比如中国大陆的的管理机构是CNNIC,它管理2个顶级域名.cn.中国,像.com,.org这些早期的顶级域名大部分都是由美国的相关机构管理的,而二级域名则是在顶级域名的下一级,是为了细分某个顶级域名而存在的,像中国的政府网站专用域名.gov.cn里的.gov,二级域名的存在只跟相应的顶级域名有关,ICANN并不关心,所有的二级域名和IP地址的映射关系等都存在二级域名的服务器上,而顶级域名服务器则保存了它下面所有二级域名服务器的地址。

那么所有的顶级域名服务器之间怎么通信呢?这个关键角色就是根域名服务器。

根域名服务器(Root name server)

根域名服务器一共有13组,由12个不同的机构管理,具体可以在https://root-servers.org/中看到,根域名服务器中有所有的顶级域名服务器的地址。当一个DNS服务器查询不到相关的域名时,就会向根服务器查询,而根服务器会根据顶级域名的名称来回应相应的DNS服务器地址,然后发送方再向这个返回的地址去查询。

4 域名和IP地址的相互解析过程

4.1 从域名解析IP地址

在linux系统中可以用dig工具来测试域名解析流程,本文以debian为例,先安装dig工具:

sudo apt update

sudo apt install dnsutils

然后再dig -v测试一下是否安装成功。

测试一下解析fewth.com过程,输入dig +trace fewth.com,结果如下:

点击展开结果
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
; <<>> DiG 9.11.5-P4-5.1+deb10u7-Debian <<>> +trace fewth.com
;; global options: +cmd
.                       255035  IN      NS      m.root-servers.net.
.                       255035  IN      NS      j.root-servers.net.
.                       255035  IN      NS      b.root-servers.net.
.                       255035  IN      NS      f.root-servers.net.
.                       255035  IN      NS      g.root-servers.net.
.                       255035  IN      NS      d.root-servers.net.
.                       255035  IN      NS      h.root-servers.net.
.                       255035  IN      NS      c.root-servers.net.
.                       255035  IN      NS      k.root-servers.net.
.                       255035  IN      NS      e.root-servers.net.
.                       255035  IN      NS      a.root-servers.net.
.                       255035  IN      NS      l.root-servers.net.
.                       255035  IN      NS      i.root-servers.net.
.                       448832  IN      RRSIG   NS 8 0 518400 20220815050000 20220802040000 20826 . CNeNM9WwPqq41Tb6572NxGG7H8pyvSds+Twvwde9dQxj0/3w+q5rvI1l O9GitOQ46g29KfRiSuBPso8EARn0dq1ddoDvVKsKDLkIz2FDWDTPdfy1 mVheiEhdfJVtXIRXMOi2gnrXnUKu5qEMWYXhN5FexJv/SAavkZAZRNfn wqD/HRGEhXno/up4vpGODOj38aPiST2X2MVWUnQBDk2WlZ3+P48Ml6o9 2D47EA9YP4dFQAaHPp/83CfUVD7ODHr912AnjamdpcVxTqtcdV/2X2Al Jk0l3pL4qsRwdmtmjj7Z1UiNF0KhinGv0YQ8sJZYa/w+amvQcui6b7n9 ikrCAw==
;; Received 526 bytes from 100.100.2.136#53(100.100.2.136) in 0 ms

com.                    172800  IN      NS      g.gtld-servers.net.
com.                    172800  IN      NS      m.gtld-servers.net.
com.                    172800  IN      NS      h.gtld-servers.net.
com.                    172800  IN      NS      k.gtld-servers.net.
com.                    172800  IN      NS      b.gtld-servers.net.
com.                    172800  IN      NS      e.gtld-servers.net.
com.                    172800  IN      NS      l.gtld-servers.net.
com.                    172800  IN      NS      f.gtld-servers.net.
com.                    172800  IN      NS      d.gtld-servers.net.
com.                    172800  IN      NS      c.gtld-servers.net.
com.                    172800  IN      NS      j.gtld-servers.net.
com.                    172800  IN      NS      i.gtld-servers.net.
com.                    172800  IN      NS      a.gtld-servers.net.
com.                    86400   IN      DS      30909 8 2 E2D3C916F6DEEAC73294E8268FB5885044A833FC5459588F4A9184CF C41A5766
com.                    86400   IN      RRSIG   DS 8 1 86400 20220816050000 20220803040000 20826 . S1zeEcF/15kmRlj+0FmE6haZ3ECmcBNPA+PJi4Dor1FxAhIy+1Ab2d79 vkVd9fiUwRdoWOQzJutpkkYGzSfKMITVJ/Ft3YtzqMVfU7Tt1FEBRTPg q3Hxp0rKIGxOkyoM40bee3RgYcKT1B00qf/io816yJYgFk8jYRC+SqhK U6SkuiYmZtj4DApvAa9jjZ3SV2hf4YrnG6tCkhTiMVikPDqjT8YZk3vN u8ZLeOkomKeNQlc5zRV2xFLYq5za+9AnNk3HppZo41HJ/7/zT8cFd+pb azGxC92YDgy5aeJ2hzh5peBmfv56Wf6sBr9rg/mQrMV0WAAxCO++kE7A 4z7/7A==
;; Received 1197 bytes from 192.33.4.12#53(c.root-servers.net) in 160 ms

fewth.com.              172800  IN      NS      ns1.dnsowl.com.
fewth.com.              172800  IN      NS      ns2.dnsowl.com.
fewth.com.              172800  IN      NS      ns3.dnsowl.com.
CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN NSEC3 1 1 0 - CK0Q2D6NI4I7EQH8NA30NS61O48UL8G5 NS SOA RRSIG DNSKEY NSEC3PARAM
CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN RRSIG NSEC3 8 2 86400 20220807042404 20220731031404 32298 com. nyQi2a7merGRIIDJl6jON9PxWr6N+7GX4hkLZ/SNLZJUig+TtIvbW/Px CmtcvKF4ZLlOuFOfdXdsS7BbXBqLYfSShpe5bhW4V/uPSzL/3oL87cyO e4iupoaBgd/LmMo3CSXIr4PP/Pa2fPmYOW9duARjePBcmNb+mDkxSvo3 GzvQE8duNTYXvykq9BSlI2w7n0q1axdjZLO/Pzvhe2IXhg==
GMU5L3FUP7SSAJ81MC3PMO2FGS2TU92F.com. 86400 IN NSEC3 1 1 0 - GMU68LJ414QLM8VS4GP16VA85J8E3BEA NS DS RRSIG
GMU5L3FUP7SSAJ81MC3PMO2FGS2TU92F.com. 86400 IN RRSIG NSEC3 8 2 86400 20220809045830 20220802034830 32298 com. H07LLMd/rOYiUYaJJqdEHFJQ6B3/43L/HSvUA0Nt2mzuZM3z6+1Pvd6B 11seQdriS5Hx6TvrDpvyy2ixSKzrtM7bCvT3a6Q4XYtOriW/mmgBRrTi t8diLxiiHeIACwdFwzo/xxomkMvTVEcpE0UZGSYUhqdcA9TU6yuL/BZw zU3PJZ/oCKR1H7M2mjkcyyxmC3j1QhbgNx4Ipe4o/aPLlQ==
;; Received 912 bytes from 192.55.83.30#53(m.gtld-servers.net) in 161 ms

fewth.com.              7207    IN      A       185.199.108.153
fewth.com.              7207    IN      A       185.199.111.153
fewth.com.              7207    IN      A       185.199.110.153
fewth.com.              7207    IN      A       185.199.109.153
fewth.com.              172800  IN      NS      ns1.dnsowl.com.
fewth.com.              172800  IN      NS      ns2.dnsowl.com.
fewth.com.              172800  IN      NS      ns3.dnsowl.com.
;; Received 259 bytes from 162.159.26.234#53(ns3.dnsowl.com) in 163 ms

上面的ns1.dnsowl.com就是注册域名时绑定的dns服务器,如果短时间内再查,直接就从dns服务器的缓存返回结果了。

4.2 从IP地址解析域名

域名的管理是分层的,查询的逻辑也很好理解,那么怎么通过IP地址查询域名呢?

其实在把域名和IP地址绑定并加入互联网时,有2个操作,1个就是相应的顶级域名服务器中增加域名到IP地址的映射,而另一个操作就是把IP地址到域名的映射增加到arpa.in-addr这个2级域名下,借用《tcp/ip详解,卷一》中的一张图:

域名层次图

这里需要注意,我们域名的层次查询和保存是从上到下,而书写方式是从下到上,像图上的sun.tuc.noao.edu这个域名,.edu是顶级域名,在最上面,而域名的日常书写顺序是反过来的,所以在查询IP地址的时候也要类似的反过来写。

我们可以用dig来测试IP地址到域名的查询过程,就用图上的cnri.reston.va.us这个域名,先查到它的IP:

dig cnri.reston.va.us +short

返回:

38.100.128.118

再反过来查域名,注意要添加.in-addr.arpa后缀并把IP地址反过来写,dig ptr表示通过IP地址查域名:

dig ptr 118.128.100.38.in-addr.arpa +short

返回:

www.cnri.reston.va.us.

dig提供了一个-x选项来简化ptr查询,不用倒写IP地址,下面的指令效果相同:

dig -x 38.100.128.118 +short

注:现在很多网站都使用内容分发服务,查询到的IP地址不是他的主要服务器而是分发内容的服务器,这种情况就不能正确的反向查询

为什么没有对应的arpa.domain

把域名和IP地址分成2类不是更好吗?

因为域名可以是无限多,而IP地址的数量是有限的(特别是v4),并且互联网连接的本质身份就是IP地址而不是域名,域名只是上层的一个“接口”,没有必要也做不到让一个机构管理所有的域名