IP 协议的责任是网络互联,它在 MAC 层之上运行,使用 IP 地址将 MAC 地址转换为四位数,抽象出物理网卡的 MAC 地址,从而开发出许多“新玩法”。
例如,它被分为五种类型:A、B、C、D 和 E;公共和私有地址;子网掩码分段。只要每个小网络都同意 IP 地址的概念,无论它们在 MAC 层有多么不同,它们都可以访问 TCP/IP 协议栈,并最终汇聚到整个互联网中。
然而,随着越来越多的计算机连接到互联网,IP 地址的缺点暴露出来。主要问题是它“不够用户友好”。尽管它比 MAC 地址的十六进制数稍好,但仍然难以记住和输入。
如何解决这个问题?
解决方案在于“以火攻火”,在 IP 地址之上添加另一层抽象,将数值 IP 地址转换为更有意义且易于记住的名称。这引入了一种字符串级别的新玩法。于是,DNS(域名系统)应运而生。
域名的形式
域名是一个分层结构,由多个用‘.’分隔的单词组成。最右边的单词是顶级域名,其次是二级域名,层级从右向左递减。
最左边的部分是主机名,通常用于指示主机的用途。例如,“www”表示 Web 服务,“mail”表示邮件服务。不过,这并不是绝对的,关键是让我们容易记住。
域名不仅是 IP 地址的替代品,还有许多其他用途。
在像 Apache 和 Nginx 这样的 Web 服务器中,域名可以用来识别虚拟主机,并确定哪个虚拟主机提供外部服务。例如,在 Nginx 中可以使用server_name指令:
server {listen 80;server_nametime.geekbang.org;...}
域名本质上是一个命名空间系统,使用多级域名来划分不同的国家、地区、组织、公司和部门。每个域名都是唯一的,可以作为身份标识。
例如,假设公司 A 有一个名叫 Garb 的人,公司 B 也有一个名叫 Joe 的人。他们可以分别称为 “Garb.Company A” 和 “Joe.Company B”。即使公司 B 也有一个名叫 Garb 的人,他们也可以被标记为 “Garb.Company B”,从而有效解决重复命名的问题。
由于这个特性,域名已扩展到其他应用领域。例如,Java 的包机制使用域名作为命名空间,但顺序相反。如果极客时间要开发一个 Java 应用程序,其包名可能是org.geekbang.time。
在 XML 中,URI 被用作命名空间,这间接涉及域名的使用。
域名解析
就像访问主机需要将 IP 地址转换为 MAC 地址一样,域名也需要转换为 IP 地址。这个过程称为域名解析。
目前,全球有数十亿个网站,数十亿的互联网用户,每天在网络上发生的 HTTP 流量是天文数字。大多数请求在访问网站时是基于域名的,这使得 DNS 成为互联网的一个重要基础设施,必须确保稳定、可靠、快速和高效的域名解析。
DNS 的核心系统是一个三层树状分布式服务,对应域名的结构:
其中,根域名服务器至关重要。它必须是众所周知的,否则对下层服务器的讨论是不可能的。目前,全球共有 13 组根域名服务器,拥有数百个镜像以确保可访问性。
有了这个系统,任何域名都可以在这个树结构中从上到下查询。就像从右到左顺序遍历域名,最终获得相应的 IP 地址。
例如,如果你想访问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时,不会回到更高层次查询,而是直接从操作系统本地获取其 IP 地址。
此外,操作系统中有一个特殊的主机映射文件,通常是一个可编辑的文本文件。在 Linux 中,它位于“/etc/hosts”,在 Windows 中,它位于C:\WINDOWS\system32\drivers\etc\hosts。如果操作系统无法在缓存中找到 DNS 记录,它会查找此文件。
有了上述野生 DNS 服务器、操作系统缓存和 hosts 文件,许多域名解析工作可以轻松地在本地或本地计算机上解决。这不仅方便了用户,还减轻了各级 DNS 服务器的压力,大大提高了效率。
下图提供了当前 DNS 架构的一个相当全面的表示。
111111111111
在 Nginx 中,有一个名为“resolver”的配置指令,用于配置 DNS 服务器。如果没有它,Nginx 将无法查询域名对应的 IP,因此无法反向代理到外部网站。
resolver 8.8.8.8 valid=30s;# 指定 Google's 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 处理,确保业务服务不间断。
内部 DNS
第二种方法涉及利用 bind9 或其他开源软件设置内部 DNS 作为名称服务器,因为域名是命名空间。这样,我们可以对所有内部开发的服务使用域名;例如,数据库服务可以使用mysql.inner.app,产品服务可以表示为goods.inner.app。当启动网络通信时,不再需要硬编码 IP 地址,而是可以直接使用域名,这也结合了第一种方法的优点。
负载均衡
第三种方法结合了前两种方法——基于域名实现负载均衡。
这有两种方法可以实现,可以结合使用:
上述所有内容都是关于可信赖的 DNS。如果存在一些恶意 DNS 服务器,它们还可以篡改域名,进行更多的恶意活动。这里有两个例子:
幸运的是,互联网有许多好人,DNS 是互联网的基础设施。恶意 DNS 并不常见,所以你在浏览互联网时不需要过于担心。
这些是域名中的一些技巧和知识,了解这些有助于更好地使用和管理域名,提高互联网的使用体验。