📄 dns协议.htm
字号:
<P align=justify>每个resolver的实现都不相同,会有复杂的逻辑处理各种错误,而本文只讨论一个纲领。</P>
<P align=justify>4.3.1. 根(Stub)resolvers</P>
<P
align=justify>一种实现resolver的方法就是在支持循环查询的服务器上实现,这样可以节省PC机上的资源,也可以对查询结果缓冲进行集中管理。其它的事情就是要一个支持循环查询服务器地址的文件在PC机上,PC机上资源有限,支持一个域名数据库可能不太现实。用户必须确定所列的名字服务器支持循环查询,服务器可以拒绝进行任何客户的循环查询请求,因此用户必须向管理员核对。这种类型的服务有一些不足,因为循环查询较费时,根对UDP重发时间的选择比较难以确定,服务器会因为根的反复重发而崩溃。使用TCP或许会好,但这样会严重占用主机时间,使用TCP相当于实现一个实时的查询系统。</P>
<P align=justify>4.3.2. 资源</P>
<P
align=justify>除了自己的资源外,resolver可以访问本地服务器保存的区数据。这会使resolver的速度加快,但是也可以让缓冲数据冲掉区数据。本文中指的本地信息是说缓冲和共享区数据,在有认证数据和缓冲数据时应该优先使用认证数据。下面的算法假设所有函数被转换为一个通常的查询函数,使用下面的数据结构代表进行中的请求的状态:</P></FONT>
<TABLE cellSpacing=1 cellPadding=7 width="100%" border=1>
<TBODY>
<TR>
<TD vAlign=top width="15%"><FONT face=宋体 size=3>
<P align=justify>SNAME</FONT></P></TD>
<TD vAlign=top width="85%">
<BLOCKQUOTE><FONT face=宋体 size=3>
<P align=justify>要查询的域名</FONT></P></BLOCKQUOTE></TD></TR>
<TR>
<TD vAlign=top width="15%"><FONT face=宋体 size=3>
<P align=justify>STYPE</FONT></P></TD>
<TD vAlign=top width="85%">
<BLOCKQUOTE><FONT face=宋体 size=3>
<P align=justify>查询请求的QTYPE</FONT></P></BLOCKQUOTE></TD></TR>
<TR>
<TD vAlign=top width="15%"><FONT face=宋体 size=3>
<P align=justify>SCLASS</FONT></P></TD>
<TD vAlign=top width="85%">
<BLOCKQUOTE><FONT face=宋体 size=3>
<P align=justify>查询请求的QCLASS</FONT></P></BLOCKQUOTE></TD></TR>
<TR>
<TD vAlign=top width="15%"><FONT face=宋体 size=3>
<P align=justify>SLIST</FONT></P></TD>
<TD vAlign=top width="85%">
<BLOCKQUOTE><FONT face=宋体 size=3>
<P
align=justify>表示正在查询的名字服务器和区,它保存resolver的预测,预测希望查询的数据在什么地方,通过接收的数据,此结构内的数据会发生变化。它包括服务器地址,区内已知的服务器,历史记录,以及表示查询距离目标还有多远的标记(查询从树顶开始向下,直到目标)。</FONT></P></BLOCKQUOTE></TD></TR>
<TR>
<TD vAlign=top width="15%"><FONT face=宋体 size=3>
<P align=justify>SBELT</FONT></P></TD>
<TD vAlign=top width="85%">
<BLOCKQUOTE><FONT face=宋体 size=3>
<P
align=justify>在resolver无法从本地信息知道应该查询哪个服务器时,它就派上用场了。</FONT></P></BLOCKQUOTE></TD></TR>
<TR>
<TD vAlign=top width="15%"><FONT face=宋体 size=3>
<P align=justify>CACHE</FONT></P></TD>
<TD vAlign=top width="85%">
<BLOCKQUOTE><FONT face=宋体 size=3>
<P
align=justify>保存前一次响应的结果,因为resolver会抛弃达到TTL时间的RR,所有大部分resolver实现将接收到RR的时间转换为绝对时间,然后保存在缓冲中,resolver可以在查询时顺便将过期RR抛弃,也可定期进行维护。</FONT></P></BLOCKQUOTE></TD></TR></TBODY></TABLE><FONT
face=宋体 size=3>
<P align=justify>4.3.3. 算法</P>
<P align=justify>大体上,算法有四步:</P>
<BLOCKQUOTE>
<OL>
<LI>
<P align=justify>检查结果是否在本地,如果是则直接返回;</P>
<LI>
<P align=justify>向最合适的服务器查询;</P>
<LI>
<P align=justify>向多个服务器发出请求,直到得到响应;</P>
<LI>
<P align=justify>分析结果:</P></LI></OL>
<BLOCKQUOTE>
<UL>
<LI>
<P align=justify>如果响应给出了结果或包含名字错误,缓冲并返回结果给用户;</P>
<LI>
<P align=justify>如果响应指出更合适的服务器,缓冲这个结果,转第2步;</P>
<LI>
<P align=justify>如果响应显示CNAME,但并不是答案,缓冲CNAME,将SNAME改为CNAME
RR中的统一名称,然后转第1步;</P>
<LI>
<P
align=justify>如果响应显示服务器失败或其它不可识别的内容,从SLIST中删除此服务器,然后转第3步。</P></LI></UL></BLOCKQUOTE></BLOCKQUOTE>
<P
align=justify>第1步在缓冲内查找,如果找到了,那就返回给用户。有些resolver可以设置不使用缓冲内的数据,但并不推荐把它做为默认情况。如果resolver能够直接访问服务器的区,而且能够找到数据的认证形式,则不要使用缓冲内的数据。</P>
<P
align=justify>第2步向服务器查询需要的数据,通常的办法是寻找本地提供的服务器RR,提供SNAME,然后给出SNAME的父域名,父域名的父域名,以此类推,直到根。因此,如果SNAME=Mockapetris.ISI.EDU,查询NS
RR的顺序为Mockapetris.ISI.EDU,ISI.EDU,EDU,最后是.(根)。NS
RR列出了此区的或在SNAME之上的主机名,复制名字到SLIST,使用本地信息设置它们的地址,可能地址不可用,此时resolver有几种不同的选择,最好是进行并行搜索,一个搜索现在可用的,一个去寻找新的,当然实现起来就有麻烦了,我们把实现的一些规则列于下面:</P>
<BLOCKQUOTE>
<UL>
<LI>
<P
align=justify>加入一些限制,让请求不会进入无限循环,也不会造成对链式请求和对其它服务的链式请求,即使在有人错误配置的情况下也不能造成上述情况</P>
<LI>
<P align=justify>尽一切可以获得响应</P>
<LI>
<P align=justify>避免不必要的传输</P>
<LI>
<P align=justify>尽快获得响应</P></LI></UL></BLOCKQUOTE>
<P align=justify>如果查询NS
RR失败,resolver从SBELT中初始化SLIST,基本的思想是当resolver不知道哪个服务器在工作时,它会从一个配置文件中取得相应的信息。虽然是特殊情况,但基本上要有两个根服务器地址存在于这种配置文件中。有两个是为了冗余,根服务器可以对所有的域空间进行探索,两个本地服务器将允许resolver继续尝试利用本地资源解析域名。除了名字的名字和地址,SLIST中可以保存服务器的优先查询顺序,保证高优先级在前,本地服务器在远程服务器前,也可能是由成功的统计结果得到,算法不尽相同。</P>
<P
align=justify>第3步发出请求,直到收到响应。算法基本思想是对所有列出的服务器以循环方式进行发送。实际上,要重视多穴(multihomed)主机的多个地址,在使用多个resolver的时候要注意对相同主机进行重新传输对时间的影响。SLIST通常包括一个值,用于控制和监视传输的超时。</P>
<P
align=justify>第4步涉及分析结果,resovler应该检查响应的ID域看是不是和请求的ID一致。理想的响应是从认证权威那里收到的数据,它要么给出需要的数据,要么给出名字错误。在TTL大于0的时候,结果保存于缓冲,同时结果返回给用户。如果结果指出其它服务器A,要对这个服务器A和SLIST中的主机进行比较,看是不是更合适,这可以通过比较SLIST中的匹配计数完成,这个匹配计数是通过SNAME和服务器A中的NS
RR计算得到。如果不合适,这个响应会被忽略,如果合适,结果会被缓冲,相应的服务器会进入SLIST,新的查询开始。如果响应包括CNAME,新查询将从CNAME开始,除非响应有标准格式的数据,或CNAME就中结果。</P>
<P align=justify>5.例子</P>
<P
align=justify>在我们的例子空间中,假设我们希望将根管理权分散到MIL,EDU,MIT.EDU和ISI.EDU区,我们可以按下图分配名字服务器:(认证权威将被加上括号)</P>
<P align=justify> </P><PRE> |(C.ISI.EDU,SRI-NIC.ARPA
| A.ISI.EDU)
+---------------------+------------------+
| | |
MIL EDU ARPA
|(SRI-NIC.ARPA, |(SRI-NIC.ARPA, |
| A.ISI.EDU | C.ISI.EDU) |
+-----+-----+ | +------+-----+-----+
| | | | | | |
BRL NOSC DARPA | IN-ADDR SRI-NIC ACC
|
+--------+------------------+---------------+--------+
| | | | |
UCI MIT | UDEL YALE
|(XX.LCS.MIT.EDU, ISI
|ACHILLES.MIT.EDU) |(VAXA.ISI.EDU,VENERA.ISI.EDU,
+---+---+ | A.ISI.EDU)
| | |
LCS ACHILLES +--+-----+-----+--------+
| | | | | |
XX A C VAXA VENERA Mockapetris</PRE>
<P
align=justify>根名字服务器在C.ISI.EDU,SRI-NIC.ARPA和A.ISI.EDU,MIL域由SRI-NIC.ARPA和A.ISI.EDU支撑;EDU域由SRI-NIC.ARPA和C.ISI.EDU,服务器拥有的区可以连接也可以不连接,本例中,C.ISI.EDU和根及EDU域连接,A.ISI.EDU和根及MIL域有连接,但和ISI.EDU有一个不连接的区。</P>
<P align=justify>5.1. C.ISI.EDU名字服务器</P>
<P align=justify>C.ISI.EDU是IN级的根,MIL,EDU域的名字服务器,也拥有这些域的区,对根域的区数据如下:</P><PRE> . IN SOA SRI-NIC.ARPA. HOSTMASTER.SRI-NIC.ARPA. (
870611 ;serial
1800 ;refresh every 30 min
300 ;retry every 5 min
604800 ;expire after a week
86400) ;minimum of a day
NS A.ISI.EDU.
NS C.ISI.EDU.
NS SRI-NIC.ARPA.
MIL. 86400 NS SRI-NIC.ARPA.
86400 NS A.ISI.EDU.
EDU. 86400 NS SRI-NIC.ARPA.
86400 NS C.ISI.EDU.
SRI-NIC.ARPA. A 26.0.0.73
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -