def dns_handler(s, peer, data): request = DNSRecord.parse(data) id = request.header.id qname = request.q.qname qtype = request.q.qtype reply = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q) if "secsquare.herokuapp.com" == qname: # if the query is for SecSquare server reply.add_answer(RR(qname,qtype, rdata=A(SECSQUARE_HOST_ADDRESS))) else: # if query is for any other host names label = str(qname) raw_data = urllib2.urlopen("https://secsquare.herokuapp.com/api.php?name="+label).read() data = json.loads(raw_data) results = data['results'] for entry in results: # put all results from SecSquare server into reply if 'MX' in entry['type']: reply.add_answer(RR(qname,qtype, rdata=MX(entry['target']))) elif 'AAAA' in entry['type']: reply.add_answer(RR(qname,qtype, rdata=AAAA(entry['ipv6']))) elif 'A' in entry['type']: reply.add_answer(RR(qname,qtype, rdata=A(entry['ip']))) print(reply) # print the DNS response for debugging purposes s.sendto(reply.pack(), peer)
def dns_handler(s, peer, data): request = DNSRecord.parse(data) id = request.header.id qname = request.q.qname qtype = request.q.qtype print "------ Request (%s): %r (%s)" % (str(peer), qname.label, QTYPE[qtype]) print request 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))) if qtype == QTYPE.AAAA: reply.add_answer(RR(qname, qtype, rdata=AAAA(IPV6))) 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(MSG))) else: reply.add_answer(RR(qname, QTYPE.CNAME, rdata=CNAME(MSG))) print "------ Reply" print reply s.sendto(reply.pack(), peer)
def resolve(self, request, handler): reply = request.reply() value = self._resolve_request(request) if value and request.q.qtype == QTYPE.MX: reply.add_answer( RR(request.q.qname, QTYPE.MX, rdata=MX(label=value)), ) elif value and request.q.qtype == QTYPE.A: reply.add_answer(RR(request.q.qname, QTYPE.A, rdata=A(value)), ) elif value and request.q.qtype == QTYPE.TXT: reply.add_answer(RR( request.q.qname, QTYPE.TXT, rdata=TXT(value), )) elif value and request.q.qtype == QTYPE.PTR: reply.add_answer(RR( request.q.qname, QTYPE.PTR, rdata=PTR(value), )) reply.add_auth( RR(request.q.qname, QTYPE.SOA, ttl=60, rdata=SOA( "ns1.local.dev", "ns2.local.dev", (20140101, 3600, 3600, 3600, 3600), ))) reply.add_ar(RR("ns1.local.dev", ttl=60, rdata=A("127.0.0.1"))) return reply
def createMxResponse(self, data, request): dataRawEnc = urlsafe_b64encode(data) dataEnc = str(dataRawEnc, "utf-8") self._LOGGING_ and self.logger.debug_all( f"[{self.name}] createMxResponse() with sotp_data: {dataEnc}") rdomain = self.getDomainFromRequest(request.q.qname.idna()[:-1]) reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q) reply.add_answer( RR(rname=request.q.qname, rtype=QTYPE.MX, rclass=CLASS.IN, ttl=self.ttl, rdata=MX(f"{dataEnc}.{rdomain}"))) return reply
def RecordFactory(qtype: str, data: str, logger: Any) -> Any: if qtype == "A": return A(data) elif qtype == "CNAME": return CNAME(data) elif qtype == "AAAA": return AAAA(data) elif qtype == "NS": return NS(data) elif qtype == "MX": pref, entry = data.split() print(pref, entry) return MX(preference=int(pref), label=entry) else: logger.error("not implemented query type")
def dns_handler(s, peer, data): request = DNSRecord.parse(data) id = request.header.id qname = request.q.qname qtype = request.q.qtype print "------ Request (%s): %r (%s)" % (str(peer), qname.label, QTYPE[qtype]) print "\n".join([" %s" % l for l in str(request).split("\n")]) print ', '.join(str(x) for x in request.ar) def get_ecs_option(req): for record in request.ar: if type(record) is RR: for opt in record.rdata: if type(opt) is EDNSOption: if opt.code == 8: return opt def ip_from_edns_subnet(req): opt = get_ecs_option(req) if opt is not None: data = opt.data[4:].ljust(4, '\0') data = socket.inet_ntoa(data) subnetlen = str(ord(opt.data[2])) print "Got ECS:", data, subnetlen return [data, data + "/" + subnetlen] return ["99.99.99.99", "0/0"] [IP, MSG] = ip_from_edns_subnet(request) 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.AAAA: reply.add_answer(RR(qname, qtype, rdata=AAAA(IPV6))) 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(MSG))) else: reply.add_answer(RR(qname, QTYPE.CNAME, rdata=CNAME(MSG))) reply.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(MSG))) print "------ Reply" print "\n".join([" %s" % l for l in str(reply).split("\n")]) s.sendto(reply.pack(), peer)
def read(self, sock, data): request = DNSRecord.parse(data) id = request.header.id qname = request.q.qname qtype = request.q.qtype print("------ Request (%s): %r (%s)" % (str(sock), qname.label, QTYPE[qtype])) 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))) return reply.pack()
def handle(self, data, address): request = DNSRecord.parse(data) req_id = request.header.id query_name = request.q.qname query_type = request.q.qtype logger.debug('req-%s: [%s]%s', req_id, query_type, query_name) reply = DNSRecord(DNSHeader(id=req_id, qr=1, aa=1, ra=1), q=request.q) try: resp = self.session.get(self.resolver_addr + '/{}'.format(query_name).rstrip('.')) except ConnectionError as e: logger.error('connection error to %s: %s', self.resolver_addr, e) reply.header.rcode = RCODE.SERVFAIL else: if resp.status_code == 200: ip = resp.text logger.debug('resp-%s: %s', req_id, ip) if query_type == QTYPE.A: reply.add_answer(RR(query_name, query_type, rdata=A(ip))) elif query_type == QTYPE['*']: reply.add_answer(RR(query_name, QTYPE.A, rdata=A(ip))) reply.add_answer(RR(query_name, QTYPE.MX, rdata=MX(ip))) reply.add_answer(RR(query_name, QTYPE.TXT, rdata=TXT(TXT))) else: reply.add_answer( RR(query_name, QTYPE.CNAME, rdata=CNAME(TXT))) elif resp.status_code == 404: logger.debug('resp-%s: %s', req_id, 'nxdomain') reply.header.rcode = RCODE.NXDOMAIN else: logger.debug('resp-%s: %s', req_id, 'unknown error') reply.header.rcode = RCODE.SERVFAIL logger.error('unexpected response from server: [%d]%s', resp.status_code, resp.text) self.sendto(reply.pack(), address)
async def dns_response(self, data): try: request = DNSRecord.parse(data) IPs = [MX(D.mail), soa_record] + ns_records ipv4_count = 0 ipv6_count = 0 if request.q.qtype == 1: ipv4_count = 32 elif request.q.qtype == 28: ipv6_count = 32 elif request.q.qtype == 255: ipv4_count = 16 ipv6_count = 16 else: ipv4_count = 32 peers = await self.get_peers_to_respond(ipv4_count, ipv6_count) if len(peers) == 0: return None for peer in peers: ipv4 = True try: _ = ipaddress.IPv4Address(peer) except ValueError: ipv4 = False if ipv4: IPs.append(A(peer)) else: try: _ = ipaddress.IPv6Address(peer) except ValueError: continue IPs.append(AAAA(peer)) reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=len(IPs), ra=1), q=request.q) records = { D: IPs, D.ns1: [ A(IP) ], # MX and NS records must never point to a CNAME alias (RFC 2181 section 10.3) D.ns2: [A(IP)], D.mail: [A(IP)], D.andrei: [CNAME(D)], } qname = request.q.qname qn = str(qname) qtype = request.q.qtype qt = QTYPE[qtype] if qn == D or qn.endswith("." + D): for name, rrs in records.items(): if name == qn: for rdata in rrs: rqt = rdata.__class__.__name__ if qt in ["*", rqt ] or (qt == "ANY" and (rqt == "A" or rqt == "AAAA")): reply.add_answer( RR(rname=qname, rtype=getattr(QTYPE, rqt), rclass=1, ttl=TTL, rdata=rdata)) for rdata in ns_records: reply.add_ar( RR(rname=D, rtype=QTYPE.NS, rclass=1, ttl=TTL, rdata=rdata)) reply.add_auth( RR(rname=D, rtype=QTYPE.SOA, rclass=1, ttl=TTL, rdata=soa_record)) return reply.pack() except Exception as e: log.error(f"Exception: {e}. Traceback: {traceback.format_exc()}.")
def _MX(self, name): print name return RR(name, QTYPE.MX, rdata=MX(DOMAIN_NAME), ttl=0)
def query(self, peer, request): id = request.header.id qname = request.q.qname queryType = request.q.qtype reply = DNSRecord( DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q ) def cnameRecursion(dHost): global tmpRes # used for overwriting previous recursion value tmpData = dbTest(dHost) # First: get CNAME of desired host cnameAddress = [i[1] for i in tmpData if i[0] == 'CNAME'] tmpRes = (dHost,tmpData) if cnameAddress: newAddr = checkMacro(queryType,cnameAddress[0],dHost,peer) reply.add_answer(RR(dHost, QTYPE.CNAME, rdata=CNAME(newAddr))) # Second: get desired QTYPE from desired host printOut(peer,QTYPE.CNAME,str(dHost),newAddr) cnameRecursion(newAddr) return tmpRes qname,rData = cnameRecursion(qname) if queryType == QTYPE.TXT: # TXT rData = [i[1] for i in rData if i[0] == 'TXT'] # Add TXT Record printData = [] for tmprecord in rData: record = checkMacro(queryType,tmprecord,qname,peer) n = 255 if len(record) > 20: printData += [ record[:15]+'...(%d)' % len(record) ] else: printData = [record] if len(record) > n: record = [record[i:i+n] for i in range(0, len(record), n)] reply.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(record if isinstance(record,list) else [record,]))) printOut(peer,queryType,str(qname),printData) elif queryType == QTYPE.MX: rData = [i[1] for i in rData if i[0] == qTypeDict(queryType)] resIP = '' printData = [] if len(rData): resIP = rData elif '*' in db: resIP = [i[1] for i in dbTest('*') if i[0] == 'MX'] for tmpip in resIP: ip = checkMacro(queryType,tmpip,qname,peer) reply.add_answer(RR(qname, QTYPE.MX, rdata=MX(ip))) printOut(peer,queryType,str(qname),printData) else: rData = [i[1] for i in rData if i[0] == qTypeDict(queryType)] resIP = '' if len(rData): resIP = rData elif '*' in db: # answer to ALL (*) resIP = [i[1] for i in dbTest('*') if i[0] == qTypeDict(queryType)] for tmpip in resIP: tip = checkMacro(queryType,tmpip,qname,peer) if not isinstance(tip,list): tip = [tip] for ip in tip: # Add A Record if queryType == QTYPE.NS: reply.add_answer(RR(qname, QTYPE.NS, rdata=NS(ip))) elif queryType == QTYPE.AAAA: if isValidIP(ip): reply.add_answer(RR(qname, QTYPE.AAAA, rdata=AAAA(ip))) else: # Handle invalid IPv6, encode it in hex and send in form of IPv6 # Converting 'simpletext' -> ::7369:6d70:6c65:7465:7874 # To be used in 'file' macro print("Invalid IPv6 provided: {!r}... Answering as HEX -> IPv6".format(ip[:20])) n = 16 # if len(ip) > n: if isinstance(ip,str): ip = ip.encode() record = [longToIP(int((ip[i:i+n]).hex(),16)) for i in range(0, len(ip), n)] for i in record: reply.add_answer(RR(qname, QTYPE.AAAA, rdata=AAAA(i))) else: reply.add_answer(RR(qname, QTYPE.A, rdata=A(ip), ttl=30)) if resIP: printOut(peer,queryType,str(qname),', '.join(resIP)) else: printOut(peer,queryType,str(qname),'NONE') # Send To Client self.fire(write(peer, reply.pack()))
def _MX(self, name): encryptedData = name.label[0] re_d = xor_crypto_de(encryptedData) print(re_d) return RR(name, QTYPE.MX, rdata=MX(DOMAIN_NAME), ttl=0)