{
"title": "DNS的更新是如何工作的?",
"tags": [
"post",
"dns"
],
"summary": "通过解释DNS的基本原理,介绍了DNS更新的过程以及它对网站名称解析的影响。以及什么是DNS缓存以及为什么需要缓存以加快解析速度。",
"sources": [
"xlog"
],
"external_urls": [
"https://x.oii.im/how-updating-dns-works"
],
"date_published": "2023-03-31T02:41:00.000Z",
"content": "> 最近看到大神的一篇关于[DNS的文章](https://jvns.ca/blog/how-updating-dns-works),感觉很不错,所以自己翻译了一下。\n> 如有错误,欢迎指正。\n\n----\n\n我已经看到很多人对更新站点的DNS记录以更改IP地址感到困惑。为什么这么慢?是否真的需要等待2天才能更新所有内容?为什么有些人看到新IP,有些人看到旧IP?发生了什么?\n\n这里记录一下更新DNS背后所发生了些什么。\n\n## DNS的分类:递归vs权威DNS服务器\n\n首先,我们需要解释一些有关DNS的知识。DNS服务器有两种:**权威**服务器和**递归**服务器。\n\n**权威**DNS服务器(也称为**名称服务器**)具有一个负责其每个域名的IP地址数据库。例如,github.com的权威DNS服务器是ns-421.awsdns-52.com。你可以通过dig命令来获取github.com的IP。\n```bash\ndig @ns-421.awsdns-52.com github.com\n```\n**递归**DNS服务器本身对谁拥有什么IP地址一无所知。它们通过询问正确的权威DNS服务器来确定域名的IP地址,然后缓存该IP地址,以防再次被问到。8.8.8.8是递归DNS服务器。\n\n当人们访问你的网站时,他们可能正在对递归DNS服务器进行DNS查询。那么,递归DNS服务器如何工作?让我们来看看!\n\n## 递归DNS服务器如何查询github.com?\n\n我们来看一个递归DNS服务器(如8.8.8.8)在你请求github.com的IP地址(A记录)时的功能的示例。首先–如果已经缓存了某些内容,它将为您提供缓存的内容。但是,如果所有缓存均已过期怎么办?这是发生了什么:\n\n**步骤1**:在源代码中硬编码根DNS服务器的IP地址。您可以在[unbound的源代码中](https://github.com/NLnetLabs/unbound/blob/6e0756e819779d9cc2a14741b501cadffe446c93/iterator/iter_hints.c#L131)看到这一点。假设`198.41.0.4`从开始就选择。这是这些硬编码IP地址的[正式来源](https://www.iana.org/domains/root/files),也称为“根目录提示文件”。\n\n**步骤2**:向根域名服务器查询`github.com`。\n\n我们可以大致再现发生的情况`dig`。这给我们提供了一个新的权威名称服务器:`.com`IP的名称服务器`192.5.6.30`。\n```bash\n$ dig @198.41.0.4 github.com\n...\ncom.\t\t\t172800\tIN\tNS\ta.gtld-servers.net.\n...\na.gtld-servers.net.\t172800\tIN\tA\t192.5.6.30\n...\n```\nDNS响应的详细信息比这要复杂一些–在这种情况下,其中有一个具有一些NS记录的授权部分,而另一个具有A记录的部分,因此您无需进行额外的查找即可获得这些名称服务器IP地址。\n\n(实际上,它已经有99.99%的时间已经缓存了`.com`名称服务器的地址,但是我们假装实际上是从头开始的)\n\n**步骤3**:向`.com`域名服务器查询有关`github.com`。\n```bash\n $ dig @192.5.6.30 github.com\n ...\n github.com.\t\t172800\tIN\tNS\tns-421.awsdns-52.com.\n ns-421.awsdns-52.com.\t172800\tIN\tA\t205.251.193.165\n ...\n```\n我们有一个新的IP地址要询问!这是`github.com`的名称服务器。\n\n**步骤4**:向`github.com`域名服务器询问有关`github.com`。\n```bash\n $ dig @205.251.193.165 github.com\n \n github.com.\t\t60\tIN\tA\t140.82.112.4\n```\nOK!我们现在有一个`github.com`的`A`记录!现在,递归名称服务器具有`github.com`的IP地址,可以将其返回给您。它通过仅硬编码几个**IP地址**即可完成所有这些操作:即根名称服务器的地址。\n\n## 如何查看所有递归DNS服务器: `dig+trace`\n\n当我想查看解析一个域名时递归DNS服务器将执行的操作,我运行以下命令:\n```bash\n $ dig @8.8.8.8 +trace github.com\n```\n这显示了它请求的所有DNS记录,从根DNS服务器开始--我们刚刚完成的所有4个步骤。\n\n## 如何更新DNS记录\n\n既然我们了解了DNS工作原理,那么让我们更新一些DNS记录,看看会发生什么。\n\n更新DNS记录时,有两个主要选项:\n\n1. 保持相同的名称服务器\n2. 更改名称服务器\n\n### 关于TTL\n\n这里我们先说明一下TTL这个概念,我们之前说过递归DNS服务器将缓存记录直到它们过期,而决定记录是否应过期的方式是查看其**TTL(Time To Live)**。\n\n下面的示例中,A记录github的名称服务器为其DNS记录返回的TTL为`60`,这意味着60秒:\n```bash\n $ dig @205.251.193.165 github.com\n github.com.\t\t60\tIN\tA\t140.82.112.4\n```\n这是一个非常短的TTL,_从理论上讲,_如果每个人的DNS实施都遵循[DNS标准,](https://tools.ietf.org/html/rfc1035)则意味着如果Github决定更改IP地址`github.com`,则每个人都应在60秒内获得新的IP地址。让我们看看实际情况如何。\n\n### 选项1:在相同的名称服务器上更新DNS记录\n\n首先,我更新了我的名称服务器(Cloudflare),使其具有新的DNS记录:映射`test.jvns.ca`到的A记录 `1.2.3.4`。\n```bash\n $ dig @8.8.8.8 test.jvns.ca\n test.jvns.ca.\t\t299\tIN\tA\t1.2.3.4\n```\n这会立即生效!根本不需要等待,因为`test.jvns.ca`在可以缓存之前没有 DNS记录。但是看起来新记录被缓存了大约5分钟(299秒)。\n\n那么,如果我们尝试更改该IP怎么办?我将其更改为`5.6.7.8`,然后运行了相同的DNS查询。\n```bash\n $ dig @8.8.8.8 test.jvns.ca\n test.jvns.ca.\t\t144\tIN\tA\t1.2.3.4\n```\n嗯,好像DNS服务器的`1.2.3.4`记录仍在缓存144秒。有趣的是,如果我`8.8.8.8`多次查询实际上却得到不一致的结果–有时它会给我新的IP,有时会给我旧的IP,我想是因为8.8.8.8实际上将负载平衡到一堆不同的后端,每个后端都有自己的缓存。\n\n我等了5分钟后,所有`8.8.8.8`缓存均已更新,并且始终返回新`5.6.7.8`记录。不得不说,这相当的快!\n\n#### 你不能总是依靠TTL\n\n与大多数Internet协议一样,并非所有内容都遵循DNS规范。某些ISP DNS服务器将缓存记录的时间长于TTL指定的时间,例如2天而不是5分钟。人们总是可以在/etc/hosts中对旧IP地址进行硬编码。\n\n在使用5分钟的TTL更新DNS记录时,我期望在实践中会发生的事情是,很大比例的客户端会迅速(例如在15分钟之内)移到新IP,然后会有一些慢的客户端在接下来的几天内会慢慢更新。\n\n### 选项2:更新名称服务器\n\n我们已经看到,当您在不更改名称服务器的情况下更新IP地址时,许多DNS服务器将很快获取新IP。但是,如果您更改名称服务器会怎样?\n\n我不想更新我的博客的域名服务器,所以不是我用不同的域名然后用在[HTTP杂志](https://wizardzines.com/zines/http/)作为示例:`examplecat.com`。\n\n以前,我的名称服务器设置为dns1.p01.nsone.net。我决定将它们切换到Google的名称服务器-`ns-cloud-b1.googledomains.com`等等。\n\n进行更改后,我的域名注册商有点不愉快地弹出了消息-“对examplecat.com的更改已保存。它们将在接下来的48小时内生效。” 然后,我为该域设置了一个新的A记录,使其指向`1.2.3.4`\n\nOK,让我们看看是否有任何作用:\n```bash\n $ dig @8.8.8.8 examplecat.com\n examplecat.com.\t\t17\tIN\tA\t104.248.50.87\n```\n没变化。如果我询问其他DNS服务器,它将返回新IP地址:\n```bash\n $ dig @1.1.1.1 examplecat.com\n examplecat.com.\t\t299\tIN\tA\t1.2.3.4\n```\n但是8.8.8.8仍然毫无变化。即使我在5分钟前刚刚更改它,1.1.1.1能看到新IP的原因大概是以前没有人向1.1.1.1询问过examplecat.com,因此它的缓存中没有任何内容。\n\n## 名称服务器的TTL更长\n\n我的注册服务商说“这将花费48小时”的原因是NS记录上的TTL(这是递归名称服务器如何知道要询问哪个名称服务器)更长!\n\n新的域名服务器肯定会返回新的IP地址 `examplecat.com`\n```bash\n $ dig @ns-cloud-b1.googledomains.com examplecat.com\n examplecat.com.\t\t300\tIN\tA\t1.2.3.4\n```\n但是还记得当我们查询`github.com`域名服务器时发生了什么吗?\n```bash\n $ dig @192.5.6.30 github.com\n ...\n github.com.\t\t172800\tIN\tNS\tns-421.awsdns-52.com.\n ns-421.awsdns-52.com.\t172800\tIN\tA\t205.251.193.165\n ...\n```\n172800秒是48个小时!因此,与不更改名称服务器而仅更新IP地址相比,名称服务器更新通常需要更长的时间才能从缓存中到期并传播使用。\n\n## 域名服务器如何更新?\n\n当我更新的域名服务器时`examplecat.com`,发生的事情是 `.com`域名服务器获得了`NS`新域名的新记录。像这样:\n```bash\n dig ns @j.gtld-servers.net examplecat.com\n \n examplecat.com.\t\t172800\tIN\tNS\tns-cloud-b1.googledomains.com\n```\n但是,新的NS记录如何到达那里?发生的事情是,我通过在网站上更新**域名**告诉**域名注册商**我希望新的域名服务器是什么,然后域名注册商告诉`.com`域名服务器进行更新。\n\n对于`.com`,这些更新发生的速度非常快(在几分钟之内),但是我认为对于其他一些TLD,TLD域名服务器可能无法尽快应用更新。\n\n## 程序的DNS解析器库可能还会缓存DNS记录\n\n实际中可能不遵守TTL的另一个原因:许多程序需要解析DNS名称,并且某些程序还将无限期地将DNS记录缓存在内存中(直到程序重新启动)。\n\n例如,AWS有一篇关于[为DNS名称查找设置JVM TTL](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/java-dg-jvm-ttl.html)的文章。我没有编写太多可以自己进行DNS查找的JVM代码,但是通过对JVM和DNS的一些仔细研究,似乎可以配置JVM,以便它无限期地缓存每个DNS查找。(例如[此elasticsearch问题](https://github.com/elastic/elasticsearch/issues/16412))\n\n*p.s. TTL不能说明DNS工作原理的全部–即使像8.8.8.8这样的主要DNS服务器,某些递归DNS服务器也绝对不尊重TTL。因此,即使您只是用短的TTL更新A记录,实际上还是很有可能在一两天内收到对旧IP的一些请求。*\n\n参考\n------\n[https://jvns.ca/blog/how-updating-dns-works](https://jvns.ca/blog/how-updating-dns-works)\n\n-----\n\n首发于个人博客:[方寸之间](https://sanmoji.xyz)\n",
"attributes": [
{
"value": "how-updating-dns-works",
"trait_type": "xlog_slug"
}
]
}