我有一个带有 3 个 TXT 记录的 DNS 域:
$ORIGIN example.com.
@ IN TXT "thing one veryveryveryveryveryverylong"
@ IN TXT "thing two veryveryveryveryveryverylong"
@ IN TXT "thing three veryveryveryveryveryverylong"
当我执行 DNS 查询(dig example.com. txt
)时,答复适合 UDP 数据包,因为有效负载小于 512 字节(导致数据包小于 576 字节)。
但是我知道如果答复足够长,它将被截断,并且 DNS 客户端将不得不使用具有更长长度限制的 TCP 重复请求。
如何在不生成 DNS 记录和执行查询的情况下计算是否超出长度限制?
我假设公式如下:
N: the number of TXT records on that label.
P: the number of bytes in all the TXT records.
S: the total number of text segments (TXT records can have multiple text segments per record)
UDP is required if N*a + P*b + S*c is more than 512
a、b 和 c 的值是多少?
(或者我走错方向了?)
答案1
实际上,在实施 TXT 记录之前,您不应该试图预先计算其确切的响应大小。有许多变量在起作用,其中一些变量您无法控制。大多数管理员根据他们从权威服务器观察到的现有 TXT 记录响应的大小进行概括,然后就结束了。由于您的问题的重点是如何避免概括来说,这个答案将集中于为什么难以使用精确计算。
(这个答案不应被看作是支持或反对试图保持在 512 字节以内的声明,而是对所采用的方法的评论。)
sDNSHeader + sQuestion + sAnswer + sAuthority + sAdditional
- 查询本身显示在问题部分回复数据包,必须予以考虑。
- 正如您所猜测的,还必须考虑答案的数量及其字节长度。
- 如果权威服务器配置为在权威部分列出名称服务器并在附加部分列出相应的地址记录,则也必须将这些考虑在内。
- 如果请求在附加部分内包含 EDNS0 伪部分,则兼容服务器将使用自己的伪部分进行回复。如果 EDNS0是在发挥作用,但仍需要考虑,特别是因为通信路径中的网络硬件可能会错误地拒绝大于 512 字节的 DNS 数据包并将其视为无效,并强制将有效消息限制恢复到原始限制。
- RFC 1035消息压缩也是一个因素。
您能编写一个程序或脚本来为您完成所有这些计算吗?当然可以。这对于您试图解决的问题来说是一种很好的时间利用吗?可能不是。使用区域内的现有 TXT 记录作为粗略的大小指导方针,如果担心超过 512 字节,请确保您熟悉利用 TXT 记录的相关标准中内置的任何“包含”功能。(SPF 等)
答案2
历史上,您会获得 512 个八位字节的 DNS 有效负载,其中 10 个八位字节是固定标头。您必须为将包含在响应中的问题部分的副本腾出空间。这大约是问题名称加上四个八位字节。每个 TXT RR 将使用一个压缩指针,指向问题名称,作为其所有者名称。这是两个八位字节。然后是 10 个八位字节的固定开销(ttl、class、type 和 rdlen)。与多个离散 TXT RR 相比,您可以将更多文本放入一个非常长的 TXT RR 中。通常,您应该尝试在其中一个区域中输入一堆不同的 TXT RR,然后使用“dig”来获取每个 TXT RR,并查看“dig”所说的有效负载有多长。
历史性的 512 数字是为 IPv4 选定的,但并未为 IPv6 放宽。在 IPv4 中,有效载荷加上最坏情况的 UDP 和 IP 报头将产生一个 568 八位字节的 IP 数据报,这是允许的最小重组缓冲区大小 —— 如果 IPv4 终端站不能重组至少那么多,它就不是“兼容的”,因此,任何人都不能假设你可以重组更多。
在现代 DNS 中,缓冲区大小将使用 OPT RR(“EDNS0”)进行协商,通常为 4096。这反映了终端站实际上可以重新组装的远大于 568 八位字节的大小。显然,大于以太网 MTU(或发现路径 MTU)的 EDNS0 缓冲区大小将导致 IP 碎片,并且这通常会导致丢失,因为防火墙不允许这样做。当 EDNS0 @4K 失败时,它通常会在 1460 重试(为 IP 和 UDP 标头以及您的有效负载留出空间并仍适合以太网数据包),然后在 512 重试,然后可能在没有 EDNS0(也是 512)的情况下重试。如果您依赖 EDNS,您通常会发送 TC=1(“发生截断”),在这种情况下请求者可能会使用 TCP 重试,或者直接失败。
这意味着如果您依赖超过 512,那么您将大量使用 TCP。由于您的问题是关于 UDP,这可能意味着您应该适合 512。
答案3
如果我正确理解了 RFC1035,则有:
Header: 12 bytes
Question: querylen +1(null term)+4
Answer: N*(namelen+1+10+(S*(1+txtlen)))
因此,对于您的示例(每个 TXT 记录只有一个文本段 S):
query = example.com
querylen = 11
name: I'm not sure if that would be blank or example.com in your example
but I think it would be example.com, so
namelen = 11
txtlen1 = 38
txtlen2 = 38
txtlen3 = 40
因此,我们有 12+11+5=28 + 答案
P1 = Answer1 = 11+11+1+38 = 61
P2 = Answer1 = 11+11+1+38 = 61
P3 = Answer1 = 11+11+1+40 = 63
28+61+61+63=213
答案4
TXT 记录最多可容纳 255 字节数据,UDP 数据包大小任意。UDP 数据包将被分段以适合 65,507 的 IP。