我有一个指向单个 IP 的 DNS 记录(例如:test.example.com):
test.example.com IN A 192.0.2.1
工作正常。现在我有 +30 个 IP 回答这个问题,例如:
teste.example.com IN A 192.0.2.1
teste.example.com IN A 192.0.2.2
(...)
teste.example.com IN A 192.0.2.31
现在它不稳定(“找不到主机”错误)。使用时dig
我收到警告“已截断,正在以 TCP 模式重试”。经过一些 Google 搜索后,我发现多 IP 查询必须不超过 512 个字节,以保证使用 UDP,并避免额外的查询(或无 TCP DNS 客户端或提供商、旧 DNS 软件等的问题)。
那么,我如何知道单个 DNS 条目中可以有多少个 v4 IP 来保证最多 512 字节的 UDP 应答?
或者
是否可以配置 ISC Bind 在多 IP 查询中仅返回一个 IP?我知道 IP 可以用 循环rrset-order { order cyclic; };
。
喜欢:
> test.example.com
Server: x.x.x.x
Address: x.x.x.x:53
Name: test.example.com
Address: 192.0.2.6
那么,只有其中一个?谢谢。
答案1
现在它不稳定(“找不到主机”错误)
从哪里/如何?
正如您所注意到的,所有正确设置的解析器都会在通过 UDP 进行的第一次查询时获得一个 Truncated 标志,然后切换到 TCP,一切都会正常。
当然,你记得 DNS 是通过 UDP 进行的和TCP(与流行的神话相反),因此您需要确保您的权威名称服务器可以通过 TCP 进行查询,一切都会好起来。
经过谷歌搜索,我发现多 IP 查询必须不超过 512 字节才能保证使用 UDP
视情况而定。有时可能会超过 1000。但最重要的是,一切都会回退到 TCP,所以应该不会有问题(可能只是性能略有下降)。
并避免额外的查询(或无 TCP DNS 客户端或提供商、旧 DNS 软件等的问题)。
“no-tcp dns 客户端或提供商”不应该存在,因为它毫无意义,而且违反了 40 多年前制定的 DNS 规范!或者您有这些案例的具体证据?
不要试图绕过这样的事情。如果这些软件存在,它们就会被破坏,并且会产生大量其他问题,例如 DNSSEC 安全域。
那么,我如何知道单个 DNS 条目中可以有多少个 v4 IP 来保证最多 512 字节的 UDP 应答?
一般来说,这个问题无法回答(因为取决于名称),但最重要的是,尝试以这种方式优化事物是徒劳的。
无论如何,您可以轻松地进行计算:
- UDP 数据包在数据前有 8 字节的报头(RFC 768)
- DNS 数据包(参见 RFC 1035)有一个标头(12 字节),然后是问题(可变数量的字节,请参阅下文),然后是答案(请参阅下文),并且我们将附加部分和授权部分视为空。
因此,DNS问题+答案已经有512-8-12 = 492字节了。
答案是,A
记录将为名称(可变长度)+ 类型(2 字节)+ 类(2 字节)+ TTL(4 字节)+ 长度(2 字节),然后是数据。A
数据为 4 字节(IPv4 地址)。
问题是名称(可变长度)+类型(2字节)+类(2字节)。
DNS 数据包中的名称具有以下两个属性:
- 它们被编码为以长度为前缀的标签列表
- 可能会被压缩,使得给定的名称或名称的一部分仅出现一次。
例如,example.com
在 DNS 中编码为 7、e、x、a、m、p、l、e、3、c、o、m、0,其中每个长度为一个字节,但如果稍后需要该名称,它将被仅使用 2 个字节的指针替换。
如果我们采用这个名字:
- 所讨论的名称部分的大小为:13 个字节,因此问题的总大小为:13 + 2 + 2 = 17
- 在答案中,每个名称可以是一个 2 字节的指针,引用问题中的名称,因此答案中的每个记录的长度为 2 个字节(其中名称为 2 个字节),然后是上面的其余部分,所以是 16 个字节。
因此,完整的 DNS 数据包的大小为 12(标头)+ 17(问题)+ x 乘以 16,其中 x 是A
记录数。
因此我们必须解决:512 = 8 + 12 + 17 + 16x
对于 x,结果x=29
为 左右。请记住,这是在最佳情况下(没有附加/授权记录,并且使用完整名称压缩)并且针对特定名称(但如果使用压缩,则名称在问题中仅出现一次,因此只有大小会发生变化)。
[另外,顺便说一句,不要被上个世纪的传统互联网所束缚;如今 IPv6 应该成为常态;当然,AAAA
在固定大小的 DNS 数据包中放入的记录类型比 IPv4 的还要少 :-) ]
是否可以将 ISC Bind 配置为在多 IP 查询中仅返回一个 IP?
我不这么认为,如果它存在,bind 将如何选择返回哪个 IP?如果您在这里,您可以自行决定在区域文件中仅列出一个 IP。或者,如果您真的很喜欢这个想法(但同样,您在此浪费的所有时间都不会防止其他问题,因为客户端存在错误,所以您无论如何都在尝试对抗无限山丘),您可以尝试dnsdist
这是一种瑞士军刀,可以进行微调。
PS:还要记住,DNS 有一个扩展,允许一方指定它可以接收的 (UDP) 缓冲区大小。请参阅 RFC 6891。最近在那里dig
用作1232
默认设置。您可能对一般情况感兴趣,请查看https://kb.isc.org/docs/aa-01219或 2020 年 DNS 标志日https://dnsflagday.net/2020/那正是关于这一点的。