跳到主要内容

3. 通配符域名对响应的影响

3. 通配符域名对响应的影响 (Impact of a Wildcard Domain Name on a Response)

RFC 1034 第 4.3.2 节中的算法保持不变, 但本文档第 3.3.3 节另有规定的部分除外. 问题在于如何解释 RFC 1034 第 4.3.2 节算法第 3 步 'c' 部分, 也就是 RFC 1034 第 4.3.3 节定义通配符时所指出的内容.

在以下说明中, 凡提到 RFC 1034 的地方, 相应文本也适用于已经应用 RFC 1034 的任何更新时的情况, 例如定义 DNAME 的 [RFC2672].

3.1 第 2 步 (Step 2)

搜索算法第 2 步是 "find the longest match possible". 有观点认为, 缓存的转介 (referral) 已经回答了 "longest match" 的问题, 因而无需继续执行后续步骤. 这是不正确的. 完成第 2 步包括确定在 DNS 层次结构的更深处是否存在更长的匹配.

3.2 第 3 步 (Step 3)

RFC 1034 第 4.3.2 节搜索算法的第 3 步是调用通配符的位置, 但前提是在该域名处没有找到与查询类型匹配的资源记录集. 这对应第 3 步的 'c' 部分. 引文如下:

# c. If at some label, a match is impossible (i.e., the
# corresponding label does not exist), look to see if [...]
# the "*" label exists.
#
# If the "*" label does not exist, check whether the name
# we are looking for is the original QNAME in the query
# or a name we have followed due to a CNAME. If the name
# is original, set an authoritative name error in the
# response and exit. Otherwise just exit.
#
# If the "*" label does exist, match RRs at that node
# against QTYPE. If any match, copy them into the answer
# section, but set the owner of the RR to be QNAME, and
# not the node with the "*" label. [...]

3.3 部分 'c' (Part 'c')

本节讨论 RFC 1034 第 4.3.2 节第 3 步 'c' 部分中引用的 "look to see" 文本.

3.3.1 最近包围者和合成源 (Closest Encloser and the Source of Synthesis)

"最近包围者 (closest encloser)" 是区域中现有域名树里的一个节点, 它与查询名称匹配的标签数量最多 (从根标签向下连续计数). 每一次匹配都是一个 "标签匹配 (label match)", 匹配标签数量的计数就是 "最近包围者证明 (closest encloser proof)". 从某种意义上说, 最近包围者是区域中作为查询名称祖先的最深现有域名.

"合成源 (source of synthesis)" 是从最近包围者直接派生下来的通配符域名, 前提是区域中该位置确实出现了通配符域名. 合成源通过在最近包围者前添加星号标签 ("*") 来确定.

使用短语 "合成源" 来描述参与通配符合成的通配符域名, 提供了一个有用术语. 这不会妨碍描述那些星号标签不在最左侧标签位置的名称的用法, 因为它们并不是通配符域名.

3.3.2 最近包围者和合成源示例 (Closest Encloser and Source of Synthesis Examples)

为便于说明, 使用第 2.2.1 节中的示例区域:

对于查询名称 "host.example.", 最近包围者是 "example.", 合成源是 "*.example.".

对于查询名称 "a.host.example.", 最近包围者是 "host.example.", 合成源本应是 "*.host.example.", 但该通配符域名不是区域的一部分且并不存在.

对于查询名称 "_telnet._tcp.host.example.", 存在精确匹配, 因而不存在合成源. 这是因为精确匹配优先于通配符匹配.

对于查询名称 "_dns._udp.host.example.", 最近包围者是 "host.example.", 合成源是 "*.host.example.", 但该通配符域名在区域中不存在, 因而没有合成源.

对于查询名称 "*.example.", 存在精确匹配, 因而不存在合成源.

对于查询名称 "a..example.", 最近包围者是 ".example.", 合成源是 "..example.", 但它在区域中不存在, 因此没有合成源.

对于查询名称 "_telnet._tcp..example.", 最近包围者是 ".example.", 合成源是 "..example.", 但它在区域中不存在, 因此没有合成源.

对于查询名称 "host3..example.", 最近包围者是 ".example.", 合成源是 "..example.", 但它在区域中不存在. 因而没有合成源. 这个例子有启发性的一点是, "host3.*.example." 确实存在, 但它既不是自身的合成源, 也不是任何其他名称的合成源.

这些示例的重点并不是名称服务器作为权威服务器会给出什么答案 (无论是答案, 转介, NXDOMAIN 还是 NOERROR/NODATA), 而是如何识别最近包围者和合成源.

3.3.3 类型匹配 (Type Matching)

RFC 1034 第 4.3.3 节写道:

# When the appropriate conditions are met, the name server creates
# RRs with an owner name equal to the query name and contents taken
# from the wildcard RRs.

还写道:

# If the "*" label does exist, match RRs at that node against QTYPE.
# If any match, copy them into the answer section, but set the owner
# of the RR to be QNAME, and not the node with the "*" label.

第一段引文描述了通过改变 RR 的所有者名称, 从通配符 RRSet 合成记录. 第二段引文要求 "match RRs ... against QTYPE", 并且只在匹配时复制. 显然, 只有 QTYPE 类型的 RR 可以被复制, 这与所有名称匹配的情况相同. 当 QTYPE 不是 CNAME 时 (或 QTYPE 为 ANY 时), 不会发生 CNAME 匹配. CNAME 的存在会阻止任何其他类型存在.

在通配符 CNAME 的情况下, CNAME RRSet 不匹配非 CNAME 查询, 因而不会用于合成. 这类似于终端节点中存在的 CNAME RRSet 在所请求类型不是 CNAME 或 ANY 时被忽略.

对于通配符 CNAME RRSet, 描述合成的语句已经修改. RFC 1034 中的文本为:

# If the "*" label does exist, match RRs at that node against QTYPE.
# If any match, copy them into the answer section, but set the owner
# of the RR to be QNAME, and not the node with the "*" label. Go
# to step 6.

修改为:

# If the "*" label does exist, match RRs at that node against QTYPE.
# If any match, copy them into the answer section, but set the owner
# of the RR to be QNAME, and not the node with the "*" label.
# If QTYPE is CNAME, continue with step 3.d.
# If QTYPE is not CNAME and a CNAME RRSet exists at the node,
# copy the CNAME RRSet into the answer section,
# but set the owner of the RRSet to be QNAME,
# and not the node with the "*" label.
# Go to step 6.

混淆源于 RFC 1034 中的以下段落:

# To illustrate the use of wildcard RRs, suppose a large company with
# a large IT staff wanted to provide a TELNET gateway

造成混淆的是这个示例. 它似乎暗示, 从通配符合成出的 CNAME RR 随后会被用于获取地址, 从而回答 A 查询. 一种解释是, 通配符是一种 "宏展开 (macro expansion)", 而该示例说明了存在通配符 CNAME 时如何回答 A 查询. 另一种解释是, 这是一个特殊情况. 第三种解释是, 通配符应在区域数据加载到服务器时展开, 然后在没有特殊展开规则的情况下应用.

工作组采纳的立场是, 该示例属于异常情况, 其作用更多是制造混淆而不是提供说明. 通过修改算法措辞, 该示例被揭示为通配符的一种错误用法.