From 0c75a3fcbee8be914d516a1f5fac746b6794bc88 Mon Sep 17 00:00:00 2001 From: Jordi Massaguer Pla Date: Sun, 19 Nov 2017 23:43:20 +0100 Subject: [PATCH] Return multiple records for domain If we return multiple records, that is an array, instead of a single record, we can make DNS Round Robin, and so, we can have "Decentralized High Availability". Signed-off-by: Jordi Massaguer Pla --- lib/dnsServer/__init__.py | 11 ++++- lib/dnsServer/namecoindns.py | 79 +++++++++++++++++---------------- plugin/pluginNamespaceDomain.py | 8 ++-- 3 files changed, 54 insertions(+), 44 deletions(-) diff --git a/lib/dnsServer/__init__.py b/lib/dnsServer/__init__.py index 67f943e..527d02a 100644 --- a/lib/dnsServer/__init__.py +++ b/lib/dnsServer/__init__.py @@ -34,6 +34,7 @@ import getopt import traceback import threading +import types from utils import * from common import * @@ -189,10 +190,16 @@ def format_question(question, qtype, qclass): return q def format_resource(resource, question): + if type(resource) == types.DictType: + tmp_r = resource + if type(resource) == types.ListType: + if len(resource) != 1: + raise Exception("Resource has more than one element and don't know what to do", resource) + tmp_r = resource[0] r = '' r += labels2str(question) - r += struct.pack("!HHIH", resource['qtype'], resource['qclass'], resource['ttl'], len(resource['rdata'])) - r += resource['rdata'] + r += struct.pack("!HHIH", tmp_r['qtype'], tmp_r['qclass'], tmp_r['ttl'], len(tmp_r['rdata'])) + r += tmp_r['rdata'] return r #def read_config(): diff --git a/lib/dnsServer/namecoindns.py b/lib/dnsServer/namecoindns.py index f702938..377e228 100644 --- a/lib/dnsServer/namecoindns.py +++ b/lib/dnsServer/namecoindns.py @@ -102,45 +102,48 @@ def get_response(self, query, domain, qtype, qclass, src_addr): if domain.endswith(".bit") or domain.endswith(".tor") : #response = listdns.lookup(self.sp, {"query":query, "domain":domain, "qtype":qtype, "qclass":qclass, "src_addr":src_addr}) #response = self.sp.lookup({"query":query, "domain":domain, "qtype":qtype, "qclass":qclass, "src_addr":src_addr}) - response = answers results = [] - if type(response) == types.DictType : - tempresults = {"qtype":response["type"], "qclass":response["class"], "ttl":response["ttl"]} - if response["type"] == 1 : - #if answers == [] : - # return self.get_response(query, domain, 5, qclass, src_addr) - tempresults["rdata"] = struct.pack("!I", ipstr2int(response["data"])) - elif response["type"] == 2 or response["type"] == 5: - tempresults["rdata"] = labels2str(response["data"].split(".")) - elif response["type"] == 16 : - tempresults["rdata"] = labels2str(response["data"]) - elif response["type"] == 15 : - tempresult = struct.pack("!H", response["data"][0]) - tempresult += labels2str(response["data"][1].split(".")) - tempresults["rdata"] = tempresult - elif response["type"] == 28 : - tempresults["rdata"] = response["data"] - elif response["type"] == 52 : - tempresult = '\x03\x00' - tempresult += chr(int(response["data"][0][0])) - tempresult += bytearray.fromhex(response["data"][0][1]) - tempresults["rdata"] = tempresult - #else : return 3, [] - results.append(tempresults) - return 0, results - if type(response) == types.StringType : - if self.isIP(response) : - return 0, [{"qtype":1, "qclass":qclass, "ttl":300, "rdata":struct.pack("!I", ipstr2int(response))}] - return 3, [] - #if query not in self._answers: - #return 3, [] - #if qtype in self._answers[query]: - #if domain == "sonicrules.bit": - # results = [{'qtype': 1, 'qclass':qclass, 'ttl': 300, 'rdata': struct.pack("!I", ipstr2int(self.reqobj.req("sonicrules.org", qtype=1).answers[0]["data"]))}] - # return 0, results - #elif qtype == 1: - # if they asked for an A record and we didn't find one, check for a CNAME - #return self.get_response(query, domain, 5, qclass, src_addr) + for response in answers: + print "response", response + print "type", type(response) + if type(response) == types.DictType: + print "dictype" + tempresults = {"qtype":response["type"], "qclass":response["class"], "ttl":response["ttl"]} + if response["type"] == 1 : + #if answers == [] : + # return self.get_response(query, domain, 5, qclass, src_addr) + tempresults["rdata"] = struct.pack("!I", ipstr2int(response["data"])) + elif response["type"] == 2 or response["type"] == 5: + tempresults["rdata"] = labels2str(response["data"].split(".")) + elif response["type"] == 16 : + tempresults["rdata"] = labels2str(response["data"]) + elif response["type"] == 15 : + tempresult = struct.pack("!H", response["data"][0]) + tempresult += labels2str(response["data"][1].split(".")) + tempresults["rdata"] = tempresult + elif response["type"] == 28 : + tempresults["rdata"] = response["data"] + elif response["type"] == 52 : + tempresult = '\x03\x00' + tempresult += chr(int(response["data"][0][0])) + tempresult += bytearray.fromhex(response["data"][0][1]) + tempresults["rdata"] = tempresult + #else : return 3, [] + results.append(tempresults) + if type(response) == types.StringType or type(response) == types.UnicodeType : + print "string type" + if self.isIP(response) : + results.append([{"qtype":1, "qclass":qclass, "ttl":300, "rdata":struct.pack("!I", ipstr2int(response))}]) + #if query not in self._answers: + #return 3, [] + #if qtype in self._answers[query]: + #if domain == "sonicrules.bit": + # results = [{'qtype': 1, 'qclass':qclass, 'ttl': 300, 'rdata': struct.pack("!I", ipstr2int(self.reqobj.req("sonicrules.org", qtype=1).answers[0]["data"]))}] + # return 0, results + #elif qtype == 1: + # if they asked for an A record and we didn't find one, check for a CNAME + #return self.get_response(query, domain, 5, qclass, src_addr) + return 0, results else: #server = self.servers[random.randrange(0, len(self.servers)-1)] #answers = self.reqobj.req(name=domain, qtype=qtype, server=server).answers diff --git a/plugin/pluginNamespaceDomain.py b/plugin/pluginNamespaceDomain.py index 5cafa49..89abd30 100644 --- a/plugin/pluginNamespaceDomain.py +++ b/plugin/pluginNamespaceDomain.py @@ -227,7 +227,7 @@ def _bitLookup(self,qdict): answers = app['plugins']['dns'].getIp4(qdict["domain"]) if answers != '[]': nameData = json.loads(answers) - answers = str(nameData[0]) + answers = nameData #did we get an IP address or nothing? if answers: return answers @@ -237,7 +237,7 @@ def _bitLookup(self,qdict): answers = app['plugins']['dns'].getIp6(qdict["domain"]) if answers != '[]': nameData = json.loads(answers) - answers = str(nameData[0]) + answers = nameData #did we get an IP address or nothing? if answers: return answers @@ -247,7 +247,7 @@ def _bitLookup(self,qdict): protocol = qdict["domain"].split(".")[1][1:] answers = app['plugins']['dns'].getTlsFingerprint(qdict["domain"], protocol, port) answers = json.loads(answers) - return {"type":52, "class":1, "ttl":300, "data":answers} + return [{"type":52, "class":1, "ttl":300, "data":answers}] return def _torLookup(self,qdict): @@ -255,7 +255,7 @@ def _torLookup(self,qdict): answers = app['plugins']['dns'].getOnion(qdict["domain"]) if answers != '[]': nameData = json.loads(answers) - answers = str(nameData[0]) + answers = nameData #did we get an IP address or nothing? if answers: #if TXT record