为了分散平时的课业压力,计网课程设计选了小学期,不过课程内容都是一样的。
要写一个DNS服务器。提供一个A记录列表,要求对于本地存在的记录,若查询结果为0.0.0.0,返回NX_DOMAIN,其他结果正常返回。对于本地处理不了的请求,转发到另一个DNS服务器进行递归查询。要求支持并发查询
如果仅仅简单的完成功能的话,不需要对于报文进行完整的解读,只需要简单的看下ID,读下query看看能不能处理,然后组个只有一个RR的包就可以了。远程DNS服务器发回来的包也不需要仔细解读,只需要取报文前两个字节做下ID转换就行了。
若要进行更为细致的解读,则需要支持域名标识符解压功能,因为绝大多数DNS服务器在返回结果的时候,都会重用域名标识符后缀来进行压缩。除此之外,支持压缩功能也是极好,因为有的DNS服务器在查询一些CDN域名的时候,会返回10多条RR记录,解压之后无压缩重新组包会轻而易举的越过DNS报文512字节的限制,从而导致Malformed Packet。
在为DNS服务器添加cache功能的时候,我发现了一个有意思的现象:我看过的所有具有多个RR的DNS应答报文,RR的TTL都是相同的。与其他同学交流后发现,有的同学看到了不同TTL的DNS应答报文。上网查询资料,RFC 2181 Section 5.2里面是这么说的
Resource Records also have a time to live (TTL). It is possible for the RRs in an RRSet to have different TTLs. No uses for this have been found that cannot be better accomplished in other ways. This can, however, cause partial replies (not marked “truncated”) from a caching server, where the TTLs for some but not all the RRs in the RRSet have expired.
Consequently the use of differing TTLs in an RRSet is hereby deprecated, the TTLs of all RRs in an RRSet must be the same.
也就是说TTL最好是一样的,于是我就大胆假设我们用的上级服务器是遵守了RFC 2181中的建议,随便从RRSet当中抽了一个RR中的TTL当成整个应答报文的TTL(一般只要TTL错的不是特别离谱,就不会影响DNS服务器的功能性)。
在实际的代码编写与调试当中,我遇到了不同线程的DNS报文对象中的一部分数据“窜”线程的现象。trouble shoot一下午发现原来是碰到了python的默认参数陷阱。在所有的类的构造函数中都把参数深拷贝一份,就把问题解决了。
未完待续