def on_udp_query(self, req_data, addr): start_time = time.time() try: request = DNSRecord.parse(req_data) if len(request.questions) != 1: xlog.warn("query num:%d %s", len(request.questions), request) return domain = str(request.questions[0].qname) type = request.questions[0].qtype if type not in [1, 28]: xlog.warn("query:%s type:%d", domain, type) # xlog.debug("DNS query:%s type:%d from %s", domain, type, addr) ips = self.query(domain, type) reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1, auth=1), q=request.q) for ip_cn in ips: ipcn_p = ip_cn.split("|") ip = ipcn_p[0] if "." in ip and type == 1: reply.add_answer(RR(domain, ttl=60, rdata=A(ip))) elif ":" in ip and type == 28: reply.add_answer(RR(domain, rtype=type, ttl=60, rdata=AAAA(ip))) res_data = reply.pack() self.serverSock.sendto(res_data, addr) xlog.debug("query:%s type:%d from:%s, return ip num:%d cost:%d", domain, type, addr, len(reply.rr), (time.time()-start_time)*1000) except Exception as e: xlog.exception("on_query except:%r", e)
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(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(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) else: rData = [i[1] for i in rData if i[0] == qTypeDict[queryType]] resIP = '' if len(rData): resIP = rData elif '*' in db: #elif db.has_key('*'): #python2 only resIP = [i[1] for i in dbTest('*') if i[0] == 'A'] for tmpip in resIP: ip = checkMacro(tmpip,qname,peer) # Add A Record reply.add_answer(RR(qname, QTYPE.A, rdata=A(ip))) 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 dns_response(self, data): request = DNSRecord.parse(data) logger.debug('%s', request) reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q) qname = request.q.qname qn = str(qname) if qn.endswith('.'): qn = qn[:-1] qtype = request.q.qtype qt = QTYPE[qtype] qnhost, qndomain = qn.split('.', 1) # # OK, so we are not conformant to the standards at all, as we never # return any SOA records and stuff... # if qndomain == settings.IPAUTH_DNSSERVER_DOMAIN: if qt in ['*', 'A']: for u in User.objects.filter(iptouser__isnull=False): if qnhost == username_to_hostname(u.username): for itu in u.iptouser_set.all(): reply.add_answer( RR( rname=qname, rtype=QTYPE.A, rclass=1, ttl=self.server.command.options['ttl'], rdata=A(itu.ip_addr), )) elif qn.endswith('.in-addr.arpa'): if qt in ['*', 'PTR']: qn = qn[:-len('.in-addr.arpa')] parts = qn.split('.') if len(parts) == 4: ip = '.'.join(reversed(parts)) try: iptu = IpToUser.objects.get(ip_addr=ip) fqdn = (username_to_hostname(iptu.user.username) + '.' + settings.IPAUTH_DNSSERVER_DOMAIN + '.') reply.add_answer( RR( rname=qname, rtype=QTYPE.PTR, rclass=1, ttl=self.server.command.options['ttl'], rdata=PTR(fqdn), )) except IpToUser.DoesNotExist: pass logger.debug('%s', reply) return reply.pack()
def _reply(self, rec, addr=None): reply = DNSRecord(DNSHeader(id=rec.header.id, qr=1, aa=1, ra=1), q=rec.q) if addr: qtype = QTYPE.A if QTYPE.A == rec.q.qtype else QTYPE.AAAA reply.add_answer(RR(rec.q.qname, qtype, rdata=A(addr))) rep = reply.pack() return rep
def take_from_cache(key, ident): name = '.'.join(key.split('.')[:-1]) header = DNSHeader(id=ident, aa=0, qr=1, ra=1, rcode=0) question = DNSQuestion(name, REV_TYPES_DICT[key.split('.')[-1]]) answer = DNSRecord(header=header, q=question) for rec in cache[key]: answer.add_answer(rec) return answer.pack()
def manufactory_DNS(self): response_packet = DNSRecord() response_packet.header.id = self.query_id response_packet.add_question(DNSQuestion(self.qname, self.qtype)) related_rr = filter(lambda rr: self.qname in rr, intercept_rr) for answer in related_rr: response_packet.add_answer(*RR.fromZone(answer)) self.response_packet = response_packet.pack().__str__()
def _reply(self, rec, addrs=None): reply = DNSRecord(DNSHeader(id=rec.header.id, qr=1, aa=1, ra=1), q=rec.q) if addrs: if not isinstance(addrs, list): addrs = [addrs] for addr in addrs: reply.add_answer(RR(rec.q.qname, QTYPE.A, rdata=A(addr))) return reply.pack()
def send_dns_packet(sock, server_addr, name, ip, id): """ Construct and send dns packet """ ans = DNSRecord(DNSHeader(id=id, qr=1)) ans.add_question(DNSQuestion(name)) ans.add_answer(RR(name, ttl=3600, rdata=A(ip))) # print(ans) sock.sendto(ans.pack(), (server_addr, 7131))
def handle_dns_packet(self, query: DNSRecord, answer: DNSRecord): if self.domain and query.q.qname.matchSuffix(self.domain): if query.q.qtype in (QTYPE.A, QTYPE.ANY): dnsname = query.q.qname.stripSuffix(self.domain) ipaddr = self.get_hostname_ip(dnsname.label[-1]) if ipaddr: answer.add_answer( RR(rname=query.q.qname, rtype=QTYPE.A, ttl=3600, rdata=RDMAP["A"](inet_ntoa(ipaddr))) ) return self
def handle_dns_packet(self, query: DNSRecord, answer: DNSRecord): if query.q.qname.matchSuffix(self.suffix): try: local_a = DNSRecord.parse(query.send(self.address, port=self.port)) for rr in local_a.rr: answer.add_answer(rr) return True except: pass finally: return True
def handle_dns_packet(self, query: DNSRecord, answer: DNSRecord): if query.q.qname.matchGlob(self.glob): try: local_a = DNSRecord.parse( query.send(self.address, port=self.port, timeout=1.0)) for rr in local_a.rr: answer.add_answer(rr) return True except: pass finally: return True
def genDefaultError(self, request): 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.TXT, rclass=CLASS.IN, ttl=self.server.ttl, rdata=TXT( "google-site-verification=qt5d8b2252742f0bcab14623d9714bee9ba7e82da3" ))) return reply
def construct_response(quest_rec, response, rec_id): dns_hdr = DNSHeader(id=rec_id, qr=1, aa=1, ra=1) dns_q = DNSQuestion(quest_rec) reply = DNSRecord(dns_hdr, q=dns_q) for rr_idx in range(response.ancount): reply.add_answer( RR(quest_rec, rdata=A(response.an[rr_idx].rdata), ttl=response.an.ttl)) return reply
def handle_dns_packet(self, query: DNSRecord, answer: DNSRecord): with self.lock: name = b'.'.join(query.q.qname.label).decode('utf8') addr = self.registry.get(name) if addr is not None: if query.q.qtype in (QTYPE.A, QTYPE.ANY): for ip in self.registry.get(name): answer.add_answer( RR(rname=query.q.qname, rtype=QTYPE.A, ttl=60, rdata=RDMAP["A"](ip)) ) return self
def response_str_in_txt(request, data: str): ''' 将字符串包装在TXT记录里作为结果返回 return: bytes ''' request = DNSRecord.parse(request) qname = request.q.qname qtype = request.q.qtype reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q) reply.add_answer(RR(qname, qtype, rdata=TXT(data))) return reply.pack()
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 query(self, peer, request): id = request.header.id qname = request.q.qname print("DNS Request for qname({0:s})".format(str(qname)), file=sys.stderr) reply = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q) # Add A Record reply.add_answer(RR(qname, QTYPE.A, rdata=A("127.0.0.1"))) # Send To Client self.fire(write(peer, reply.pack()))
def dns_response(self, data): request = DNSRecord.parse(data) logger.debug('%s', request) reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q) qname = request.q.qname qn = str(qname) if qn.endswith('.'): qn = qn[:-1] qtype = request.q.qtype qt = QTYPE[qtype] qnhost, qndomain = qn.split('.', 1) # # OK, so we are not conformant to the standards at all, as we never # return any SOA records and stuff... # if qndomain == settings.IPAUTH_DNSSERVER_DOMAIN: if qt in ['*', 'A']: for u in User.objects.filter(iptouser__isnull=False): if qnhost == username_to_hostname(u.username): for itu in u.iptouser_set.all(): reply.add_answer(RR(rname=qname, rtype=QTYPE.A, rclass=1, ttl=self.server.command.options['ttl'], rdata=A(itu.ip_addr))) elif qn.endswith('.in-addr.arpa'): if qt in ['*', 'PTR']: qn = qn[:-len('.in-addr.arpa')] parts = qn.split('.') if len(parts) == 4: ip = '.'.join(reversed(parts)) try: iptu = IpToUser.objects.get(ip_addr=ip) fqdn = username_to_hostname(iptu.user.username) + \ '.' + settings.IPAUTH_DNSSERVER_DOMAIN + '.' reply.add_answer(RR(rname=qname, rtype=QTYPE.PTR, rclass=1, ttl=self.server.command.options['ttl'], rdata=PTR(fqdn))) except IpToUser.DoesNotExist: pass logger.debug('%s', reply) return reply.pack()
def handle_dns_packet(self, query: DNSRecord, answer: DNSRecord): qname = query.q.qname qtype = query.q.qtype found = False for rec in self.records: if qname == rec[0]: found = True if qtype == QTYPE.ANY: answer.add_answer(RR(rname=rec[0], rtype=rec[1], ttl=60, rdata=RDMAP.get(QTYPE.get(rec[1]))(rec[2]))) elif qtype == rec[1]: answer.add_answer(RR(rname=rec[0], rtype=rec[1], ttl=60, rdata=RDMAP.get(QTYPE.get(rec[1]))(rec[2]))) break return found
def on_udp_query(self, rsock, req_data, addr): start_time = time.time() try: request = DNSRecord.parse(req_data) if len(request.questions) != 1: xlog.warn("query num:%d %s", len(request.questions), request) return domain = utils.to_bytes(str(request.questions[0].qname)) if domain.endswith(b"."): domain = domain[:-1] type = request.questions[0].qtype if type not in [1, 28]: xlog.info("direct_query:%s type:%d", domain, type) return self.direct_query(rsock, request, addr) xlog.debug("DNS query:%s type:%d from %s", domain, type, addr) ips = self.query(domain, type) if not ips: xlog.debug("query:%s type:%d from:%s, get fail, cost:%d", domain, type, addr, (time.time() - start_time) * 1000) reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1, auth=1), q=request.q) ips = utils.to_bytes(ips) for ip_cn in ips: ipcn_p = ip_cn.split(b"|") ip = ipcn_p[0] if b"." in ip and type == 1: reply.add_answer(RR(domain, ttl=60, rdata=A(ip))) elif b":" in ip and type == 28: reply.add_answer( RR(domain, rtype=type, ttl=60, rdata=AAAA(ip))) res_data = reply.pack() rsock.sendto(res_data, addr) xlog.debug("query:%s type:%d from:%s, return ip num:%d cost:%d", domain, type, addr, len(reply.rr), (time.time() - start_time) * 1000) except Exception as e: xlog.exception("on_query except:%r", e)
def cache_hit(self): cache_key = "cache:{}:{}".format(self.qtype, self.qname) cache_ret = cache_db.get(cache_key) if cache_ret: log.info("cache_hit: {}".format(self.query_id)) response_packet = DNSRecord() response_packet.header.id = self.query_id response_packet.add_question(DNSQuestion(self.qname)) for answer in loads(cache_ret): response_packet.add_answer(answer) log.info(response_packet.__str__()) log.info("DNS response id {}".format(self.query_id)) response_packet_str = response_packet.pack().__str__() self.wfile.write(response_packet_str) return True
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 createTxtResponse(self, data, request): # I embebed sopt data in one RR in TXT Response (but you can split sotp data in multiple RR) dataRawEnc = urlsafe_b64encode(data) dataEnc = str(dataRawEnc, "utf-8") self._LOGGING_ and self.logger.debug_all( f"[{self.name}] createTxtResponse() with sotp_data: {dataEnc}") 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.TXT, rclass=CLASS.IN, ttl=self.ttl, rdata=TXT(dataEnc))) return reply
def handle_dns_packet(self, query: DNSRecord, answer: DNSRecord): addrs = [] if query.q.qtype in (QTYPE.A, QTYPE.ANY): addrs = self._storage.query(str(query.q.qname).rstrip('.')) if len(addrs): for addr in addrs: answer.add_answer( RR(rname=query.q.qname, rtype=QTYPE.A, ttl=60, rdata=RDMAP["A"](addr))) return self
def lookup_local(handler, request): qn2 = qn = request.q.qname qt = QTYPE[request.q.qtype] reply = DNSRecord( DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q ) is_local = False for value in globalvars.local_domains.values(): domain = value['domain'] if globalvars.config['smartdns']['hack_srv'] and qt == 'SRV' and \ not domain.inDomain(qn2): r_srv = b'.'.join(qn.label[:2]) if r_srv.decode().lower() in globalvars.config['smartdns']['hack_srv']: qn2 = DNSLabel(domain.get_subdomain('@')).add(r_srv) logger.warn('\tChange SRV request to %s from %s' % (qn2, qn)) if domain.inDomain(qn2): is_local = True rr_data = domain.search(qn2, qt) for r in rr_data: answer = RR( rname=r['name'], rtype=getattr(QTYPE, r['type']), rclass=1, ttl=60 * 5, rdata=r['rdata'], ) reply.add_answer(answer) if reply.rr: break if is_local: if reply.rr: lines = [] for r in reply.rr: rqn = str(r.rdata) rqt = QTYPE[r.rtype] lines.append('\t\t%s(%s)' % (rqn, rqt)) logger.info('\tReturn from LOCAL:\n%s' % '\n'.join(lines)) logger.debug('\n' + str(reply)) else: logger.info('\tReturn from LOCAL: \n\t\tN/A') handler.send_data(reply.pack()) return is_local
def read_query_a(self, request): qname = request.q.qname id = request.header.id if qname.label[0] in implant_id: if qname.label[1] == 'START': #print "Limplant envoie le debut des resultats" reponse = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q) reponse.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(dodo))) self.send_data(reponse) if qname.label[1] == 'STARTFF': #print "Limplant envoie le debut des resultats" reponse = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q) reponse.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(dodo))) self.send_data(reponse) elif qname.label[1] == 'BODY': str1 = ''.join(qname.label[2:-3]) #print "L'implant renvoie le resultat suivant: " print '\n'+str1.decode("hex") reponse = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q) reponse.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(dodo))) self.send_data(reponse) elif qname.label[1] == 'FFBODY': str1 = ''.join(qname.label[3:-3]) result.append(str1.decode("hex")) reponse = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q) reponse.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(dodo))) self.send_data(reponse) elif qname.label[1] == 'END': #print "Limplant envoie la fin des resultats" reponse = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q) reponse.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(dodo))) self.send_data(reponse) str1 = ''.join(result) print '\n'+str1 del result[:]
def generate_response(self, ip, query, q_id): if type(ip) == str: record = DNSRecord( DNSHeader(id=q_id, qr=1, aa=1, ra=1), q=DNSQuestion(query), a=RR(query, rdata=A(ip)), ) return record else: record = DNSRecord( DNSHeader(id=q_id, qr=1, aa=1, ra=1), q=DNSQuestion(query), a=RR(query, rdata=A(ip[0].address)), ) for ip_obj in ip[1:]: record.add_answer(RR(query, QTYPE.A, rdata=A(ip_obj.address))) return record
def query(self, peer, query): qname = query.q.qname print(qname) qtype = QTYPE[query.q.qtype] qclass = CLASS[query.q.qclass] response = yield self.call(lookup(qname, qclass=qclass, qtype=qtype)) record = DNSRecord( DNSHeader(id=query.header.id, qr=1, aa=1, ra=1), q=query.q, ) for rr in response.value.rr: record.add_answer(rr) yield record.pack()
def response_bytes_in_txt(request, data: bytes): ''' 将字节流包装在TXT记录里作为结果返回 return: bytes ''' assert len(data) < 256 request = DNSRecord.parse(request) qname = request.q.qname qtype = request.q.qtype reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q) reply.add_answer(RR(qname, qtype, rdata=TXT(''))) reply = reply.pack() reply[-3:-1] = struct.pack('>H', len(data) + 1) reply[-1] = len(data) reply += data return reply
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]) 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 query(self, peer, request): id = request.header.id qname = request.q.qname print( "DNS Request for qname({0:s})".format(str(qname)), file=sys.stderr ) reply = DNSRecord( DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q ) # Add A Record reply.add_answer(RR(qname, QTYPE.A, rdata=A("127.0.0.1"))) # Send To Client self.fire(write(peer, reply.pack()))
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 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 dns_response( data: AnyStr, db_path: str, protocol_type: AnyStr, deny_types: List ) -> Tuple[int, Optional[AnyStr]]: # decode a DNS packet request = DNSRecord.parse(data) qname = request.q.qname qn = str(qname) qtype = QTYPE[request.q.qtype] # query type is in denied types if (qtype in deny_types) or ("*" in deny_types): logger.warning("query has blocked.") return (RESP_BLK, None) # qr is a bit for distingushing queries(0) and reponses(1) reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q) if qn.endswith("."): query_result = query_db(qn.rstrip("."), qtype, db_path) else: query_result = query_db(qn, qtype, db_path) # hit if len(query_result) != 0: for _item in map(QueryItem._make, query_result): rdata = RecordFactory(qtype, _item.value, logger) reply.add_answer( RR( rname=qname, rtype=getattr(QTYPE, qtype), rclass=IN, ttl=_item.TTL, rdata=rdata, ) ) # need forward else: return (RESP_FWD, None) logger.debug("Reply: %s\n", reply) return (RESP_OK, reply.pack())
def dns_handler(s, peer, data): # parse request request = DNSRecord.parse(data) name, _, domain = str(request.q.qname).partition(".") # create response reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q) # fill response if request.q.qtype == QTYPE.A or request.q.qtype == QTYPE['*']: ip = db_fetch(domain, name, "A") if ip: reply.add_answer(RR(request.q.qname, request.q.qtype, rdata=A(ip))) if request.q.qtype == QTYPE.AAAA or request.q.qtype == QTYPE['*']: ip = db_fetch(domain, name, "AAAA") if ip: ip = [ord(x) for x in socket.inet_pton(socket.AF_INET6, ip)] reply.add_answer(RR(request.q.qname, request.q.qtype, rdata=AAAA(ip))) # send response s.sendto(reply.pack(), peer)
def read_query_txt(self, request): qname = request.q.qname id = request.header.id if qname.label[0] == 'NEW': sys.stdout.flush() print '\n[+] New implant! IMPLANT-ID %s' % str(id) str1 = ''.join(qname.label[1:-3]) plop = str1.decode('hex') implant_info[str(id)] = plop.split('\n') reponse = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q) reponse.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(str(id)))) implant_id.append(str(id)) self.send_data(reponse) if qname.label[0] in implant_id: if qname.label[1] == 'TOPO': now = datetime.datetime.now() localtime= now.strftime("%Y-%m-%d %H:%M") implant_info[qname.label[0]][4] = localtime if command.get(qname.label[0]): #print "[+] Implant %s poll, commandes pretes, au travail petit hippo!!" % str(qname.label[0]) reponse = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q) reponse.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(command.get(qname.label[0])))) self.send_data(reponse) del command[qname.label[0]] else: #print "[+] Implant %s poll , aucunes commandes, fait dodo petit hippo" % str(qname.label[0]) reponse = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q) reponse.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(dodo))) self.send_data(reponse) pass
def on_udp_query(self, req_data, addr): start_time = time.time() try: request = DNSRecord.parse(req_data) if len(request.questions) != 1: xlog.warn("query num:%d %s", len(request.questions), request) return domain = str(request.questions[0].qname) type = request.questions[0].qtype if type not in [1, 28]: xlog.warn("query:%s type:%d", domain, type) # xlog.debug("DNS query:%s type:%d from %s", domain, type, addr) ips = self.query(domain, type) reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1, auth=1), q=request.q) for ip_cn in ips: ipcn_p = ip_cn.split("|") ip = ipcn_p[0] if "." in ip and type == 1: reply.add_answer(RR(domain, ttl=60, rdata=A(ip))) elif ":" in ip and type == 28: reply.add_answer( RR(domain, rtype=type, ttl=60, rdata=AAAA(ip))) res_data = reply.pack() self.serverSock.sendto(res_data, addr) xlog.debug("query:%s type:%d from:%s, return ip num:%d cost:%d", domain, type, addr, len(reply.rr), (time.time() - start_time) * 1000) except Exception as e: xlog.exception("on_query except:%r", e)
def handle(self): socket = self.request[1] # gather up details on the request client_address = self.client_address[0] data = self.request[0].strip() try: request = DNSRecord.parse(data) except: logging.info("Couldn't parse query from {}:{}".format(client_address, data)) return qname = str(request.q.qname) subdomain, domain = self.name_to_subdomain_and_domain(qname) reply = None if domain in self.domain_variants or domain == self.domain: # formulate answer with record for both the 1-bit variant and the intended domain intended_domain = self.domain if subdomain: intended_domain = subdomain + "." + self.domain logging.info("Request from {} for {}".format(client_address, qname)) reply = DNSRecord( DNSHeader(id=request.header.id, qr=1, aa=2, ra=1), q=request.q, ) reply.add_answer(RR(qname,rdata=A(self.ip), ttl=self.ttl)) reply.add_answer(RR(intended_domain,rdata=A(self.ip), ttl=self.ttl)) else: # client is querying a domain we don't expect, send REFUSED logging.info("Request from {} for {} REFUSED".format(client_address, qname)) reply = DNSRecord( DNSHeader(id=request.header.id, qr=1, rcode=RCODE.REFUSED), q=request.q ) socket.sendto(reply.pack(), self.client_address)
def handle_dns_packet(self, query: DNSRecord, answer: DNSRecord): import random qname = query.q.qname qtype = query.q.qtype found = False records = [] for rec in self.records: if qname.matchGlob(rec[0]): found = True if qtype == QTYPE.A and rec[1] == QTYPE.CNAME: # self-resolve it as A additionally local_q = DNSRecord.question(rec[2], "A") local_a = DNSRecord.parse( local_q.send('localhost', port=int(getenv("DNSPORT", 5353)), timeout=1.0)) for rr in local_a.rr: records.append((qname, rr.rtype, str(rr.rdata))) # records.append((qname, rec[1], rec[2])) if qtype == QTYPE.ANY: records.append(rec) elif qtype == rec[1]: records.append(rec) random.shuffle(records) for rec in records: answer.add_answer( RR(rname=rec[0], rtype=rec[1], ttl=60, rdata=RDMAP.get(QTYPE.get(rec[1]))(rec[2]))) return found
def request(self, s, peer, data): """ Handle DNS Request @method request @param {socket} s Connection Socket @param {peer} peer Peer Connecection @param {mixed} data Data @return {void} """ # DNS Request Data request = DNSRecord.parse(data) id = request.header.id qname = request.q.qname qtype = request.q.qtype logging.info('DNS Request for qname(%s)' % qname) # Lookup IP Address ip = self.aliases.get(str(qname), False) # NOAUTH if ip is False: reply = DNSRecord( DNSHeader(id=id, qr=1, aa=1, ra=1, rcode=9), q=request.q) else: reply = DNSRecord( DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q) # Add A Record reply.add_answer(RR(qname, QTYPE.A, rdata=A(ip))) # Send To Client return self.s.sendto(reply.pack(), peer)
def resolve(self,request,handler): global HOSTS4, HOSTS6, RULE, RULE6 try: qname = request.q.qname qn = str(qname)[:-1] qtype = request.q.qtype print_log('resolve: ' + qn) if qtype == DNS_A_RECORD: server = get_server(qn, RULE) if HOSTS4.has_key(qn): reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q) for answer in HOSTS4[qn]: reply.add_answer(RR(rname=qname, rtype=qtype, rclass=1, ttl=TTL, rdata=A(answer))) else: reply = self.proxy[server[0]](request, server) elif qtype == DNS_AAAA_RECORD: server = get_server(qn, RULE6) if server[0] == 6: if HOSTS6.has_key(qn): reply = request.reply() for answer in HOSTS6[qn]: reply.add_answer(RR(rname=qname, rtype=qtype, rclass=1, ttl=TTL, rdata=AAAA(answer))) else: reply = self.cache(request, server) else: reply = request.reply() else: server = get_server(qn, RULE) if server[0] == 0: reply = self.default(request, server) else: reply = self.default6(request) except socket.timeout: reply = request.reply() return reply
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)
def dns_handler(s, peer, data): global data_received command = pick_command() msg = "C" + base64.b32encode(command).replace("=", '') beacon = False request = DNSRecord.parse(data) id = request.header.id qname = request.q.qname qtype = request.q.qtype if qname.label[2] == TARGETED_DOMAIN: data = qname.label[0] if len(data) > 10: data = data[10:] if len(data) % 8 != 0: data = data + ("=" * (8 - len(data) % 8)) decoded_data = base64.b32decode(data) if len(decoded_data) == 4: if decoded_data == decoded_data.upper(): decoded_data = decoded_data + " [BEACON]" beacon = True if data_received != "": print "[+] Decoded Data Received: %s" % (data_received) data_received = "" else: data_received += decoded_data print "[+] Raw Data Received: %s" % qname.label[0] if beacon: print "[+] Sending Command: %s | Encoded: %s" % (command, msg) if not beacon: msg = "C" reply = DNSRecord(DNSHeader(id=id, qr=1, rd=1, ra=1), q=request.q) if qtype == QTYPE.TXT: reply.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(msg))) else: reply.add_answer(RR(qname, QTYPE.CNAME, rdata=CNAME(msg))) s.sendto(reply.pack(), peer)
def dns_handler(s, peer, data): global data_received command = pick_command() msg = "C" + base64.b32encode(command).replace("=",'') beacon = False request = DNSRecord.parse(data) id = request.header.id qname = request.q.qname qtype = request.q.qtype if qname.label[2] == TARGETED_DOMAIN: data = qname.label[0] if len(data) > 10: data = data[10:] if len(data) % 8 != 0: data = data + ("=" * (8 - len(data) % 8)) decoded_data = base64.b32decode(data) if len(decoded_data) == 4: if decoded_data == decoded_data.upper(): decoded_data = decoded_data + " [BEACON]" beacon = True if data_received != "": print "[+] Decoded Data Received: %s" % (data_received) data_received = "" else: data_received += decoded_data print "[+] Raw Data Received: %s" % qname.label[0] if beacon: print "[+] Sending Command: %s | Encoded: %s" % (command, msg) if not beacon: msg = "C" reply = DNSRecord(DNSHeader(id=id, qr=1, rd=1, ra=1), q=request.q) if qtype == QTYPE.TXT: reply.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(msg))) else: reply.add_answer(RR(qname, QTYPE.CNAME, rdata=CNAME(msg))) s.sendto(reply.pack(), peer)
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 server_encrypt(dns_packet: DNSRecord, data, question): data = base64.b64encode(data) dns_packet = dns_packet.reply() dns_packet.add_answer(RR(question, rtype=QTYPE.TXT, rdata=TXT(data))) return dns_packet.pack()
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 handle(self, data, address): logging.info('receive data size=%r from %r', len(data), address) request = DNSRecord.parse(data) reply = DNSRecord(DNSHeader(id=request.header.id,qr=1,aa=1,ra=1),q=request.q) qname = request.q.qname qtype = request.q.qtype 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(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))) self.sendto(reply.pack(), address)
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")])) 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("\n".join([" %s" % l for l in str(reply).split("\n")])) s.sendto(reply.pack(), peer)
def _reply(self, rec, addr=None): reply = DNSRecord(DNSHeader(id=rec.header.id, qr=1, aa=1, ra=1), q=rec.q) if addr: reply.add_answer(RR(rec.q.qname, QTYPE.A, rdata=A(addr))) return reply.pack()
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 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 parse_request(data): """Parsing incomming data""" request = DNSRecord.parse(data) fqdn = [x.decode() for x in request.q.qname.label] city = '.'.join(fqdn[-3:-2]) if '.'.join(fqdn[-2:]) == parse_config(): # declare id_ = request.header.id rq_ = request.q qn_ = request.q.qname qt_ = request.q.qtype # generate message msg_ = get_weather(city, record=qt_) # generate dns reponse reply = DNSRecord(DNSHeader(id=id_, qr=1, aa=1, ra=1), q=rq_) if qt_ == QTYPE.A: if ('.'.join(fqdn) == parse_config(2)[0]) or ('.'.join(fqdn) == parse_config()): ip_, ttl_ = parse_config(qt_) reply.add_answer(RR(qn_, qt_, rdata=A(ip_), ttl=ttl_)) else: for ip_ in msg_: reply.add_answer(RR(qn_, qt_, rdata=A('.'.join(ip_)))) elif qt_ == QTYPE.TXT: if len(msg_) > 255: for msg in textwrap.wrap(msg_.decode(), 255): reply.add_answer(RR(qn_, qt_, rdata=TXT(msg))) else: reply.add_answer(RR(qn_, qt_, rdata=TXT(msg_))) elif qt_ == QTYPE.NS: ns_, ttl_ = parse_config(qt_) reply.add_answer(RR(qn_, qt_, rdata=NS(ns_), ttl=ttl_)) elif qt_ == QTYPE.SRV: reply.add_answer(RR(qn_, qt_, rdata=SRV(*msg_))) return reply.pack()