python开发支持edns扩展协议的dns服务器

恩,这两天正在看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差,可能要更强劲,开发起来更加的让人舒心.  

原文连接是,http://xiaorui.cc/?p=1330


还没实现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()


大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码,感谢!
另外再次标注博客原地址  xiaorui.cc

发表评论

电子邮件地址不会被公开。 必填项已用*标注