跳转至

06 域名里有哪些门道?

在上一讲里,我们学习了HTTP协议使用的TCP/IP协议栈,知道了HTTP协议是运行在TCP/IP上的。

IP协议的职责是“网际互连”,它在MAC层之上,使用IP地址把MAC编号转换成了四位数字,这就对物理网卡的MAC地址做了一层抽象,发展出了许多的“新玩法”。

例如,分为A、B、C、D、E五种类型,公有地址和私有地址,掩码分割子网等。只要每个小网络在IP地址这个概念上达成一致,不管它在MAC层有多大的差异,都可以接入TCP/IP协议栈,最终汇合进整个互联网。

但接入互联网的计算机越来越多,IP地址的缺点也就暴露出来了,最主要的是它“对人不友好”,虽然比MAC的16进制数要好一点,但还是难于记忆和输入。

怎么解决这个问题呢?

那就“以其人之道还治其人之身”,在IP地址之上再来一次抽象,把数字形式的IP地址转换成更有意义更好记的名字,在字符串的层面上再增加“新玩法”。于是,DNS域名系统就这么出现了。

域名的形式

在第4讲曾经说过,域名是一个有层次的结构,是一串用“.”分隔的多个单词,最右边的被称为“顶级域名”,然后是“二级域名”,层级关系向左依次降低。

最左边的是主机名,通常用来表明主机的用途,比如“www”表示提供万维网服务、“mail”表示提供邮件服务,不过这也不是绝对的,名字的关键是要让我们容易记忆。

看一下极客时间的域名“time.geekbang.org”,这里的“org”就是顶级域名,“geekbang”是二级域名,“time”则是主机名。使用这个域名,DNS就会把它转换成相应的IP地址,你就可以访问极客时间的网站了。

域名不仅能够代替IP地址,还有许多其他的用途。

在Apache、Nginx这样的Web服务器里,域名可以用来标识虚拟主机,决定由哪个虚拟主机来对外提供服务,比如在Nginx里就会使用“server_name”指令:

server {
    listen 80;                       #监听80端口
    server_name  time.geekbang.org;  #主机名是time.geekbang.org
    ...
}

域名本质上还是个名字空间系统,使用多级域名就可以划分出不同的国家、地区、组织、公司、部门,每个域名都是独一无二的,可以作为一种身份的标识。

举个例子吧,假设A公司里有个小明,B公司里有个小强,于是他们就可以分别说是“小明.A公司”,“小强.B公司”,即使B公司里也有个小明也不怕,可以标记为“小明.B公司”,很好地解决了重名问题。

因为这个特性,域名也被扩展到了其他应用领域,比如Java的包机制就采用域名作为命名空间,只是它使用了反序。如果极客时间要开发Java应用,那么它的包名可能就是“org.geekbang.time”。

而XML里使用URI作为名字空间,也是间接使用了域名。

域名的解析

就像IP地址必须转换成MAC地址才能访问主机一样,域名也必须要转换成IP地址,这个过程就是“域名解析”。

目前全世界有几亿个站点,有几十亿网民,而每天网络上发生的HTTP流量更是天文数字。这些请求绝大多数都是基于域名来访问网站的,所以DNS就成了互联网的重要基础设施,必须要保证域名解析稳定可靠、快速高效。

DNS的核心系统是一个三层的树状、分布式服务,基本对应域名的结构:

  1. 根域名服务器(Root DNS Server):管理顶级域名服务器,返回“com”“net”“cn”等顶级域名服务器的IP地址;
  2. 顶级域名服务器(Top-level DNS Server):管理各自域名下的权威域名服务器,比如com顶级域名服务器可以返回apple.com域名服务器的IP地址;
  3. 权威域名服务器(Authoritative DNS Server):管理自己域名下主机的IP地址,比如apple.com权威域名服务器可以返回www.apple.com的IP地址。

在这里根域名服务器是关键,它必须是众所周知的,否则下面的各级服务器就无从谈起了。目前全世界共有13组根域名服务器,又有数百台的镜像,保证一定能够被访问到。

有了这个系统以后,任何一个域名都可以在这个树形结构里从顶至下进行查询,就好像是把域名从右到左顺序走了一遍,最终就获得了域名对应的IP地址。

例如,你要访问“www.apple.com”,就要进行下面的三次查询:

  1. 访问根域名服务器,它会告诉你“com”顶级域名服务器的地址;
  2. 访问“com”顶级域名服务器,它再告诉你“apple.com”域名服务器的地址;
  3. 最后访问“apple.com”域名服务器,就得到了“www.apple.com”的地址。

虽然核心的DNS系统遍布全球,服务能力很强也很稳定,但如果全世界的网民都往这个系统里挤,即使不挤瘫痪了,访问速度也会很慢。

所以在核心DNS系统之外,还有两种手段用来减轻域名解析的压力,并且能够更快地获取结果,基本思路就是“缓存”。

首先,许多大公司、网络运行商都会建立自己的DNS服务器,作为用户DNS查询的代理,代替用户访问核心DNS系统。这些“野生”服务器被称为“非权威域名服务器”,可以缓存之前的查询结果,如果已经有了记录,就无需再向根服务器发起查询,直接返回对应的IP地址。

这些DNS服务器的数量要比核心系统的服务器多很多,而且大多部署在离用户很近的地方。比较知名的DNS有Google的“8.8.8.8”,Microsoft的“4.2.2.1”,还有CloudFlare的“1.1.1.1”等等。

其次,操作系统里也会对DNS解析结果做缓存,如果你之前访问过“www.apple.com”,那么下一次在浏览器里再输入这个网址的时候就不会再跑到DNS那里去问了,直接在操作系统里就可以拿到IP地址。

另外,操作系统里还有一个特殊的“主机映射”文件,通常是一个可编辑的文本,在Linux里是“/etc/hosts”,在Windows里是“C:\WINDOWS\system32\drivers\etc\hosts”,如果操作系统在缓存里找不到DNS记录,就会找这个文件。

有了上面的“野生”DNS服务器、操作系统缓存和hosts文件后,很多域名解析的工作就都不用“跋山涉水”了,直接在本地或本机就能解决,不仅方便了用户,也减轻了各级DNS服务器的压力,效率就大大提升了。

下面的这张图比较完整地表示了现在的DNS架构。

在Nginx里有这么一条配置指令“resolver”,它就是用来配置DNS服务器的,如果没有它,那么Nginx就无法查询域名对应的IP,也就无法反向代理到外部的网站。

resolver 8.8.8.8 valid=30s;  #指定Google的DNS,缓存30秒

域名的“新玩法”

有了域名,又有了可以稳定工作的解析系统,于是我们就可以实现比IP地址更多的“新玩法”了。

第一种,也是最简单的,“重定向”。因为域名代替了IP地址,所以可以让对外服务的域名不变,而主机的IP地址任意变动。当主机有情况需要下线、迁移时,可以更改DNS记录,让域名指向其他的机器。

比如,你有一台“buy.tv”的服务器要临时停机维护,那你就可以通知DNS服务器:“我这个buy.tv域名的地址变了啊,原先是1.2.3.4,现在是5.6.7.8,麻烦你改一下。”DNS于是就修改内部的IP地址映射关系,之后再有访问buy.tv的请求就不走1.2.3.4这台主机,改由5.6.7.8来处理,这样就可以保证业务服务不中断。

第二种,因为域名是一个名字空间,所以可以使用bind9等开源软件搭建一个在内部使用的DNS,作为名字服务器。这样我们开发的各种内部服务就都用域名来标记,比如数据库服务都用域名“mysql.inner.app”,商品服务都用“goods.inner.app”,发起网络通信时也就不必再使用写死的IP地址了,可以直接用域名,而且这种方式也兼具了第一种“玩法”的优势。

第三种“玩法”包含了前两种,也就是基于域名实现的负载均衡。

这种“玩法”也有两种方式,两种方式可以混用。

第一种方式,因为域名解析可以返回多个IP地址,所以一个域名可以对应多台主机,客户端收到多个IP地址后,就可以自己使用轮询算法依次向服务器发起请求,实现负载均衡。

第二种方式,域名解析可以配置内部的策略,返回离客户端最近的主机,或者返回当前服务质量最好的主机,这样在DNS端把请求分发到不同的服务器,实现负载均衡。

前面我们说的都是可信的DNS,如果有一些不怀好意的DNS,那么它也可以在域名这方面“做手脚”,弄一些比较“恶意”的“玩法”,举两个例子:

  • “域名屏蔽”,对域名直接不解析,返回错误,让你无法拿到IP地址,也就无法访问网站;
  • “域名劫持”,也叫“域名污染”,你要访问A网站,但DNS给了你B网站。

好在互联网上还是好人多,而且DNS又是互联网的基础设施,这些“恶意DNS”并不多见,你上网的时候不需要太过担心。

小结

这次我们学习了与HTTP协议有重要关系的域名和DNS,在这里简单小结一下今天的内容:

  1. 域名使用字符串来代替IP地址,方便用户记忆,本质上一个名字空间系统;
  2. DNS就像是我们现实世界里的电话本、查号台,统管着互联网世界里的所有网站,是一个“超级大管家”;
  3. DNS是一个树状的分布式查询系统,但为了提高查询效率,外围有多级的缓存;
  4. 使用DNS可以实现基于域名的负载均衡,既可以在内网,也可以在外网。

课下作业

  1. 在浏览器地址栏里随便输入一个不存在的域名,比如就叫“www.不存在.com”,试着解释一下它的DNS解析过程。
  2. 如果因为某些原因,DNS失效或者出错了,会出现什么后果?

欢迎你把自己的答案写在留言区,与我和其他同学一起讨论。如果你觉得有所收获,也欢迎把文章分享给你的朋友。

unpreview

精选留言(15)
  • Wendy 👍(231) 💬(12)

    比如你有一个网站要上线,你在域名注册商那里申请了abc.com,那么你的域名A记录就保存在这个域名注册商的DNS服务器上,该DNS服务器称为权威域名服务器。当客户端访问abc.com时,先查找浏览器DNS缓存,没有则查找操作系统DNS缓存,在这一阶段是操作系统dnscache clinet 服务进行DNS缓存的(你在任务管理器里面可以看到一个dns客户端进程,就是这玩意实现缓存的),如果还是没有则查找hosts文件中的域名记录。然后依然没有的话则访问电脑上设置的DNS服务器IP,比如三大营运商的dns服务器或者谷歌的8.8.8.8,此时这一层的DNS服务器称为“野生DNS缓存服务器”,也就是非权威域名服务器。如果还是没有则非权威域名服务器会去查找 根域名服务器-顶级域名服务器-二级域名服务器-权威域名服务器 ,这样客户端就在权威域名服务器上找到了abc.com对应的IP了,这个IP可以是多个,每次客户端请求的时候域名服务器会根据负载均衡算法分配一个IP给你。当DNS缓存失效了,则重新开始新一轮的域名请求。 总结如下: 浏览器缓存->操作系统dnscache ->hosts文件->非权威域名服务器->根域名服务器->顶级域名服务器->二级域名服务器->权威域名服务器。 其中非权威域名服务器还包括LDNS(企业内网DNS服务器),三大营运商DNS,谷歌公开的DNS,微软公开的DNS等。 另外DNS请求有两种方式:递归查询和迭代查询,这方面大家可以网上了解一下。LDNS往后面查询一般是递归查询,因为公司内网是有防火墙的,全部请求通过LDNS来递归查询然后把结果给内网用户。 以上为自己理解整理的,若有错误还请大家指正。

    2019-08-31

  • Yif 👍(210) 💬(17)

    GFW就是使用了这些恶意的DNS

    2019-06-10

  • 初音未来 👍(41) 💬(2)

    应该是先查找本地hosts文件,在查找缓存吧

    2019-06-12

  • 肥low 👍(36) 💬(4)

    老师好! 第一个问题: 1、检查本地dns缓存是否存在解析"www.不存在.com"域名的ip 2、如果没有找到继续查找本地hosts文件内是否有对应的固定记录 3、如果hosts中还是没有那就根据本地网卡被分配的 dns server ip 来进行解析,dns server ip 一般是“非官方”的ip,比如谷歌的“8.8.8.8”,本身它也会对查找的域名解析结果进行缓存,如果它没有缓存或者缓存失效,则先去顶级域名服务器“com”去查找“不存在.com”的域名服务器ip,结果发现不存在,于是直接返回告诉浏览器域名解析错误,当然这两次查找过程是基于udp协议 第二个问题:如果dns失效或出错,那就访问不了了呗,我现在有个域名在国外某些国家每天都有不少访问失败的http请求,客户端直接报“Failed host lookup”的错误

    2019-06-13

  • 何用 👍(33) 💬(1)

    为何全世界只有 13 组根域名服务器呢?

    2019-06-10

  • Chuan 👍(24) 💬(3)

    老师好: 对于DNS解析的过程:浏览器DNS缓存->操作系统缓存->Hosts文件->非权威域名服务器->根域名服务器->顶级域名服务器->权威域名服务器。一直对浏览器/本机如何知道根服务器地址存在疑惑。 在查阅《计算机网络自顶向下方法》后发现,我们在连接某个ISP时,ISP一般会给我们提供一个IP地址,同时该地址拥有一台或多台DNS服务器地址(通过DHCP)。所以我们在Hosts文件中找不到时,会去查询这个局域网DNS服务器,如果没有查到,它会帮我们去查询根NDS服务器、顶级域名服务器和权威域名服务器,然后返回给本机,同时进行缓存。 个人认为,如果我们自己配置了非权威DNS服务器,如8.8.8.8,它应该也会帮我们去查询根NDS服务器、顶级域名服务器和权威域名服务器。 这些远程查询都是基于UDP协议,通常使用53号端口。 不知道以上理解是否正确?

    2019-06-28

  • 👍(16) 💬(3)

    1:在浏览器地址栏里随便输入一个不存在的域名,比如就叫“www. 不存在.com”,试着解释一下它的 DNS 解析过程。 首先,非常感谢老师和评论区的同学,我的认知又被刷新了,之前只模糊认识到有一个翻译的过程,把域名解析成对应的IP地址,然而光域名解析这一个动作就有一长串组合拳,目的除了便于人类的记忆和理解,剩下的核心就是提速。 提速的关键是,第一尽可能的少做事情,第二是尽可能的少做慢动作,怎么来实现呢?合适的数据结构和算法+缓存(可能是多级缓存),这里都是有体现的,比如:域名服务器的树行结构,各种缓存机制。 OK,回答问题,这里仅是整理,我之前确实不知道有这么多门道。 第一:拿着域名去浏览器缓存中查找,这里有些疑问,浏览器中缓存在哪里?过期时间大概多久?过期机制是什么? 第二:去操作系统缓存中去查找,同样的疑问,缓存在哪里?过期时间多久?过期机制是什么?怎么确认一下? 第三:去hosts文件中查找,这个文件还好进程修改,那么每个操作系统这个文件都必须在默认的路径下吗?否则就需要全部文件遍历一下啦? 第四:去非权威DNS服务器中查找,到此这些都可以认为是一种缓存思想的运用,把域名和IP的映射关系信息放在更快的存储设备之上,把这份信息放在离用户更近的地方,来加速用户通过域名获取IP的速度。 第五:去根域名DNS服务器中查找,注意,此时仅拿着根域名去查找,下面的查找过程有一定的层次结构,这样不仅查找的信息少存储的信息也会少,速度也会更快一些 第六:去顶级域名DNS服务器中查找,此时拿的信息是“com”查找“不存在.com”,确实查不到,然后就抛出异常,逐级返回了,最后把找不到的提升信息给到用户——无法访问此网站,找不到www.不存在.com的服务器IP地址 第七:假设第六步找到了,则会继续去二级域名DNS服务器去查找,根据“不存在.com”找“ww.不存在.com” 第八:去权威DNS服务器中找到“ww.不存在.com”对应的IP地址 第九:然后返回,在返回的过程中会更新操作系统缓存,浏览器缓存,不知道非权威DNS服务器中的域名和IP映射信息是怎么进去的,是定时加载嘛? 2:如果因为某些原因,DNS 失效或者出错了,会出现什么后果? 会出现“无法访问此网站,找不到www.XXX.com的服务器IP地址”

    2020-03-24

  • 数学汤家凤 👍(11) 💬(4)

    域名解析过程 浏览器缓存 -> OS 缓存 -> hosts 文件 -> 本地域名服务器 -> 根域名服务器 -> 顶级域名服务器 -> 权威域名服务器 客户端向本地域名服务器获取,是递归查询 本地域名服务器向根域名服务器获取,可以是递归也可是迭代 递归就是你交给别人,让别人查到,在返回给你 迭代就是你找别人要,他叫你去别的地方找

    2020-07-10

  • 海盗船长 👍(10) 💬(1)

    chrome chrome://net-internals/#dns 查看和清空缓存 windows查看系统缓存: ipconfig /displaydns 显示已有缓存 ipconfig /displaydns > C:\Users\SDWQ\Desktop\1.txt 导出到再查看。 ipconfig /flushdns 强制更新缓存

    2020-05-10

  • 梦倚栏杆 👍(6) 💬(1)

    老师好,我有两个疑问: 1.终极dns的解析是有谁实现的或者谁规定的: 比如乔布斯有个苹果域名:www.apple.com,苹果电脑的官网;张三也想为水果苹果申请个域名(www.apple.com)来展示他的苹果;结果我们几乎可以猜测到,他是申请失败的,原因已经有一个苹果存在了,谁来评判这个苹果域名已经被占用了呢?判断逻辑是如何来的,如果两个申请发生在同时呢? 2. ip地址的分配和身份证号一样吗?有地址在里面吗? 比如1-45属于美国的网段,或者属于哪个超大公司的网段。如果有,那是不是就以为着预分配,也就意味着部分ip段的浪费,如果没有,那ip地址从一个地方查找另外一个地方怎么找呢?莫非每个初始的线路都需要访问到根DNS

    2019-06-10

  • Even 👍(5) 💬(1)

    有个疑问,操作系统的dns缓存存在哪里?内存还是硬盘?为什么有hosts文件还需要操作系统的dns缓存。

    2019-08-05

  • zjajxzg 👍(5) 💬(1)

    1、操作系统缓存→本地hosts文件→非核心dns服务器→根域名服务器地址→顶级域名服务器地址→二级域名服务器地址。。。 2、无法访问相应的资源

    2019-06-10

  • - shadow - 👍(3) 💬(2)

    想问问老师,域名的“新玩法”的第一种和第三种在现实环境中真的会使用吗?主要是各级缓存的存在,可能会导致找不到最新的IP,而拿到的是旧的IP呢?

    2019-09-27

  • 学无涯 👍(3) 💬(2)

    有一个问题: 权威域名服务器是因为公司大,用到的IP比较多,才给分的吗。那为什么谷歌不是权威域名服务器呢?不理解

    2019-08-07

  • 小鸟淫太 👍(3) 💬(2)

    老师您好,之前碰到过这样一个问题 域名解析返回两个IP地址,其中一个IP无法正常访问。 Safari可以自动切换到正常的IP地址继续访问 Chrome会尝试TCP连接不正常的IP,大约1分多钟之后会连接另一个IP 最终导致Chrome页面访问速度缓慢。想问下这种问题是属于浏览器问题,还是DNS的问题呢?

    2019-06-10