跳到主要内容

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 查询. 另一种解释是, 这是一个特殊情况. 第三种解释是, 通配符应在区域数据加载到服务器时展开, 然后在没有特殊展开规则的情况下应用.

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