Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 2c2d399
Showing
3 changed files
with
129 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
Python, DNS and Redis | ||
|
||
Simple servers to deliver customized DNS data. These servers rely on Redis as storage backend. | ||
|
||
Both of them rely on google's dns as fallback | ||
|
||
gevent version | ||
============== | ||
gevent_dns.py | ||
|
||
to create a new domain: | ||
set IP:name ip_addr | ||
set TXT:name txtfield | ||
|
||
twisted version | ||
=============== | ||
tx_dns.py | ||
|
||
create a new domain SET: | ||
domain.tld ip_addr |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# dns server using dnslib and gevent | ||
# based on https://bitbucket.org/paulc/dnslib/src/80d85555aae4/src/server/gevent_server.py | ||
# set the key as | ||
# set IP:name ip_addr | ||
# set TXT:name txtfield | ||
# fallback on gevent's dns resolver | ||
# gleicon 2011 | ||
|
||
|
||
import gevent | ||
from gevent import socket | ||
import gevent.dns; | ||
from gevent import monkey; | ||
monkey.patch_socket() | ||
|
||
import urllib2,sys | ||
import redis | ||
import random | ||
from dnslib import * | ||
|
||
|
||
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("IP:%s" % qname) | ||
TXT = r.get("TXT:%s" % qname) | ||
if not IP: | ||
try: | ||
IP = socket.gethostbyname(str(qname)) | ||
except Exception, 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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# Python/Twisted/Redis backed DNS server - resolves from NAME to IP addrs | ||
# fallback to google or any other DNS server to resolv domains not present on Redis | ||
# to set a new domain on redis, just issue a SET domain.tld ip_addr | ||
# run with twistd -ny txredns.tac | ||
# gleicon 2011 | ||
|
||
from twisted.names import dns, server, client, cache | ||
from twisted.application import service, internet | ||
from twisted.internet import defer | ||
from twisted.python import log | ||
import txredisapi | ||
|
||
class RedisResolverBackend(client.Resolver): | ||
def __init__(self, redis, servers=None): | ||
self.redis = redis | ||
client.Resolver.__init__(self, servers=servers) | ||
self.ttl = 5 | ||
|
||
@defer.inlineCallbacks | ||
def _get_ip_addr(self, hostname, timeout): | ||
ip = yield self.redis.get(hostname) | ||
r = None | ||
if ip: | ||
defer.returnValue([(dns.RRHeader(hostname, dns.A, dns.IN, self.ttl, dns.Record_A(ip, self.ttl)),), (), ()]) | ||
else: | ||
i = yield self._lookup(hostname, dns.IN, dns.A, timeout) | ||
defer.returnValue(i) | ||
|
||
def lookupAddress(self, name, timeout = None): | ||
return self._get_ip_addr(name, timeout) | ||
|
||
def create_application(): | ||
rd = txredisapi.lazyRedisConnectionPool() | ||
redisBackend = RedisResolverBackend(rd, servers=[('8.8.8.8', 53)]) | ||
|
||
application = service.Application("txdnsredis") | ||
srv_collection = service.IServiceCollection(application) | ||
|
||
dnsFactory = server.DNSServerFactory(caches=[cache.CacheResolver()], clients=[redisBackend]) | ||
|
||
internet.TCPServer(53, dnsFactory).setServiceParent(srv_collection) | ||
internet.UDPServer(53, dns.DNSDatagramProtocol(dnsFactory)).setServiceParent(srv_collection) | ||
return application | ||
|
||
# .tac app | ||
application = create_application() | ||
|
||
|