恩,这两天正在看dns的东西, 对dns的edns的协议很是感兴趣…. 有人估计还不知道edns是啥? 简单的来说,我们选用了google的dns地址来做dns的解析,但是如果没有扩展协议的话,我们会在之恩给你的dns层把你识别为国外的用户。 那么后来谷歌提出一个草案,并已由IETF牵头作为一个公开的标准建议,该草案叫“edns-client-subnet”,其原理是当用户请求DNS的时候,递归DNS查询服务器将用户的IP发给权威DNS服务器,权威服务器可以根据该信息返回相应的查询结果。
记得去年的时候,看到小米在开发博客里面,开源搞了一个用twisted实现的dns服务器,虽然没有在线上用,但是看了测试的结果还是有些意思的, 服务协议里面是支持edns的。 我这边也想自己开发实现一套支持edns和ip库装载在nosql中 (redis\aerospike),开发语言是python,高性能的服务架构用的是gevent, 部分代码是借鉴与一个老外的代码。 据我的经验来扯淡, gevent一点都不必twisted差,可能要更强劲,开发起来更加的让人舒心.
还没实现edns的协议版本, 这两天搞搞….
import gevent from gevent import socket import gevent.dns; from gevent import monkey; monkey.patch_socket() import redis from dnslib import * A_RECORD_PREFIX = 'DNS:PASSTHRU:A:%s' TXT_RECORD_PREFIX = 'DNS:PASSTHRU:TXT:%s' CNAME_RECORD_PREFIX = 'DNS:PASSTHRU:CNAME:%s' AF_INET = 2 SOCK_DGRAM = 2 s = socket.socket(AF_INET, SOCK_DGRAM) s.bind(('', 53)) def dns_handler(s, peer, data, r): request = DNSRecord.parse(data) id = request.header.id qname = request.q.qname qtype = request.q.qtype IP = r.get(A_RECORD_PREFIX % qname) TXT = r.get(TXT_RECORD_PREFIX % qname) CNAME = r.get(CNAME_RECORD_PREFIX % qname) if not IP: try: IP = socket.gethostbyname(str(qname)) except Exception, e: print e print 'Host not found' IP = '0.0.0.0' print "Request (%s): %r (%s) - Response: %s" % (str(peer), qname.label, QTYPE[qtype], IP) reply = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q) if qtype == QTYPE.A: reply.add_answer(RR(qname, qtype, rdata=A(IP))) elif qtype == QTYPE['*']: reply.add_answer(RR(qname, QTYPE.A, rdata=A(IP))) reply.add_answer(RR(qname, QTYPE.MX, rdata=MX(IP))) reply.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(TXT))) else: reply.add_answer(RR(qname, QTYPE.CNAME, rdata=CNAME(TXT))) s.sendto(reply.pack(), peer) def main(): r = redis.Redis() while True: data, peer = s.recvfrom(8192) gevent.spawn(dns_handler, s, peer, data, r) if __name__ == '__main__': main()