恩,这两天正在看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()
