def response(self, peer, response): id = response.header.id qname = str(response.q.qname) qtype = response.q.qtype qclass = response.q.qclass if id not in self.peers: self.logger.info( "Unknown Response ({0:s}): {1:s} {2:s} {3:s}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname)) return peer = self.peers[id] request = self.requests[id] key = (str(request.q.qname), request.q.qtype, request.q.qclass) reply = request.reply() reply.add_answer(*response.rr) self.cache[key] = reply.rr self.fire(write(peer, reply.pack())) del self.peers[id] del self.requests[id]
def response(self, peer, response): id = response.header.id qname = str(response.q.qname) qtype = response.q.qtype qclass = response.q.qclass if id not in self.peers: self.logger.info( "Unknown Response ({0:s}): {1:s} {2:s} {3:s}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname ) ) return peer = self.peers[id] request = self.requests[id] key = (str(request.q.qname), request.q.qtype, request.q.qclass) reply = request.reply() reply.add_answer(*response.rr) self.cache[key] = reply.rr self.fire(write(peer, reply.pack())) del self.peers[id] del self.requests[id]
async def __handle_response(self, response, peer): """ 本地没查到,本服务做递归DNS查询,其他服务器返回的结果 :return: """ record = DNSRecord.parse(response) id = record.header.id qname = str(record.q.qname) qtype = record.q.qtype qclass = record.q.qclass if id not in self.peers: self.logger.info( "Unknown Response ({0:s}): {1:s} {2:s} {3:s}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname)) return addr = self.peers[id] request = self.requests[id] reply = request.reply() reply.add_answer(*record.rr) del self.peers[id] del self.requests[id] self.transport.sendto(reply.pack(), addr) self.logger.info(f"==Reply from {peer}")
def ttl(self): for k, rrs in self.cache.items()[:]: if any(rr.ttl == 0 for rr in rrs): qname, qtype, qclass = k self.logger.info("Expired Entry: {0:s} {1:s} {2:s}".format( CLASS.get(qclass), QTYPE.get(qtype), qname)) del self.cache[k] else: for rr in rrs: rr.ttl -= 1
def ttl(self): for k, rrs in self.cache.items()[:]: if any(rr.ttl == 0 for rr in rrs): qname, qtype, qclass = k self.logger.info( "Expired Entry: {0:s} {1:s} {2:s}".format( CLASS.get(qclass), QTYPE.get(qtype), qname ) ) del self.cache[k] else: for rr in rrs: rr.ttl -= 1
def get_reply(self, data): global dns_cache global args host, port = self.server.resolver.address, self.server.resolver.port request = DNSRecord.parse(data) domain = str(request.q.qname) qtype = str(QTYPE.get(request.q.qtype)) index = domain + "/" + qtype if not args.no_cache and index in dns_cache: if time.time() < dns_cache[index][0]: if args is not None and args.verbose: try: display("[i] %s served value from cache: %s" % (index, ', '.join( [x.rdata for x in dns_cache[index][1]]))) except: pass rep = request.reply() rep.add_answer(*dns_cache[index][1]) return rep.pack() if args is not None and args.verbose: display("[i] domain %s requested using TCP server %s" % (domain, args.dns_server)) data = struct.pack("!H", len(data)) + data response = send_tcp(data, host, port) response = response[2:] reply = DNSRecord.parse(response) if args.verbose: try: display( "[i] %s %s resolve to %s" % (domain, qtype, ', '.join([x.rdata for x in reply.rr]))) except: pass ttl = 3600 try: ttl = reply.rr[0].ttl except Exception: try: ttl = reply.rr.ttl except Exception: pass dns_cache[index] = (int(time.time()) + ttl, reply.rr) if len(dns_cache) > DNS_CACHE_SIZE: dns_cache.popitem(last=False) return response
def extract_query(pkt): """ Returns the hostname and record type of the record.""" request = DNSRecord.parse(pkt) # Extract the hostname qname = request.q.qname hostname = str(qname) # Remove tailing period (artifact of the dnslib) if hostname[-1] == '.': hostname = hostname[:-1] # Record type qtype = QTYPE.get(request.q.qtype) return (hostname, qtype)
def GetBINDRecords(domain): file = BINDPath(domain) f = open(file, "r") body = f.read() f.close() records = RR.fromZone(body) ss = "" for r in records: host = HostConvert(r, domain) ttl = r.ttl cl = CLASS.get(r.rclass) qt = QTYPE.get(r.rtype) record = r.rdata.toZone() line = '%-23s %-7s %-7s %-7s %s' % (host, ttl, cl, qt, record) ss += line + "\n" return ss
def resolve(self, request, handler): if request.q.qtype != QTYPE.A: reply = request.reply() reply.header.rcode = RCODE.NXDOMAIN logging.debug('Request unknown qtype: {}'.format(QTYPE.get(request.q.qtype))) return reply with self.lock: data = request.q.qname part = data.stripSuffix(self.domain).idna()[:-1] if part in self.cache: response = self.cache[part] response.header.id = request.header.id return self.cache[part] response = self._resolve(request, handler) self.cache[part] = response return response
def resolve(self, request, handler): if request.q.qtype != QTYPE.A: reply = request.reply() reply.header.rcode = RCODE.NXDOMAIN logger.debug('Request unknown qtype: {}'.format(QTYPE.get(request.q.qtype))) return reply with self.lock: data = request.q.qname part = data.stripSuffix(self.domain).idna()[:-1] if part in self.cache: response = self.cache[part] response.header.id = request.header.id return self.cache[part] response = self._resolve(request, handler) self.cache[part] = response return response
def get_reply(self,data): global dns_cache global args host,port = self.server.resolver.address,self.server.resolver.port request = DNSRecord.parse(data) domain=str(request.q.qname) qtype=str(QTYPE.get(request.q.qtype)) index=domain+"/"+qtype if not args.no_cache and index in dns_cache: if time.time()<dns_cache[index][0]: if args is not None and args.verbose: try: display("[i] %s served value from cache: %s"%(index, ', '.join([x.rdata for x in dns_cache[index][1]]))) except: pass rep=request.reply() rep.add_answer(*dns_cache[index][1]) return rep.pack() if args is not None and args.verbose: display("[i] domain %s requested using TCP server %s"%(domain, args.dns_server)) data = struct.pack("!H",len(data)) + data response = send_tcp(data,host,port) response = response[2:] reply = DNSRecord.parse(response) if args.verbose: try: display("[i] %s %s resolve to %s"%(domain, qtype, ', '.join([x.rdata for x in reply.rr]))) except: pass ttl=3600 try: ttl=reply.rr[0].ttl except Exception: try: ttl=reply.rr.ttl except Exception: pass dns_cache[index]=(int(time.time())+ttl, reply.rr) if len(dns_cache)>DNS_CACHE_SIZE: dns_cache.popitem(last=False) return response
def export(self): out = [ "$TTL {0:d}".format(self.ttl), "$ORIGIN {0:s}".format(self.name.rstrip(".")), "", ] for record in self.records: rr = record.rr rname = str(rr.rname.stripSuffix(self.name)) out.append( "{0:23s} {1:7d} {2:7s} {3:7s} {4:s}".format( rname, rr.ttl, CLASS.get(rr.rclass), QTYPE.get(rr.rtype), rr.rdata.toZone() ) ) return "\n".join(out)
def dns_handler(s, message, address): try: income_record = DNSRecord.parse(message) except: logging.error('from %s, parse error' % address) return try: qtype = QTYPE.get(income_record.q.qtype) except: qtype = 'unknown' domain = str(income_record.q.qname).strip('.') info = '%s -- %s, from %s' % (qtype, domain, address) if qtype == 'A': ip = get_ip_from_domain(domain) if ip: response = reply_for_A(income_record, ip=ip, ttl=60) s.sendto(response.pack(), address) return logging.info(info) # at last response = reply_for_not_found(income_record) s.sendto(response.pack(), address) logging.info(info)
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 generate_dns_packet(request_pkt, hostname, ip_addresses): """ Generates a DNS Response populated with the provided information. Args: - request_pkt: The DNS request packet - hostname: Hostname being resolved - ip_addresses: list of ips addresses """ request = DNSRecord.parse(request_pkt) record_type = QTYPE.A response = request.reply() # TODO(kbaichoo): add flexible ttl for ip_address in ip_addresses: # Get the class for resource data that corresponse to the request # and provide the IP address. rdata = dnslib.RDMAP.get(QTYPE.get(record_type), dnslib.RD)(ip_address) response.add_answer(RR(hostname, record_type, rdata=rdata, ttl=60)) # Encode response return response.pack()
def request(self, peer, request): qname = str(request.q.qname) qtype = request.q.qtype qclass = request.q.qclass key = (qname, qtype, qclass) if key in self.cache: self.logger.info( "Cached Request ({0:s}): {1:s} {2:s} {3:s}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname)) reply = request.reply() for rr in self.cache[key]: reply.add_answer(rr) self.fire(write(peer, reply.pack())) return if key in self.hosts: self.logger.info( "Local Hosts Request ({0:s}): {1:s} {2:s} {3:s}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname)) rr = [RR(qname, rdata=A(self.hosts[key]))] reply = request.reply() reply.add_answer(*rr) self.cache[key] = rr self.fire(write(peer, reply.pack())) return records = Record.objects.filter(rname=qname, rclass=qclass, rtype=qtype) if records: self.logger.info( "Authoritative Request ({0:s}): {1:s} {2:s} {3:s}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname)) rr = [record.rr for record in records] reply = request.reply() reply.add_answer(*rr) self.cache[key] = rr self.fire(write(peer, reply.pack())) return self.logger.info("Request ({0:s}): {1:s} {2:s} {3:s}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname)) lookup = DNSRecord(q=DNSQuestion(qname, qtype, qclass)) id = lookup.header.id self.peers[id] = peer self.requests[id] = request self.fire(write((self.forward, 53), lookup.pack()))
dhdr[f2] = o.header.a dhdr[f3] = o.header.ns dhdr[f4]= o.header.ar d['questions'] = [] for q in o.questions: dq = { 'qname': str(q.qname), 'qtype': QTYPE[q.qtype], 'qclass': QTYPE[q.qclass] } d['questions'].append(dq) d['rr'] = [] for r in o.rr: dr = { 'rname': str(r.rname), 'rtype': QTYPE.lookup(r.rtype,r.rtype), 'rclass': CLASS[r.rclass], 'ttl': r.ttl, 'rdata': str(r.rdata) } d['rr'].append(dr) d['timestamp'] = packet_timedate(udp.timestamp) d['src'] = src d['sport'] = sport d['dst'] = dst d['dport'] = dport if module_data['prnt']: chop.prnt(d) if module_data['mongo']:
def request(self, peer, request): qname = str(request.q.qname) qtype = request.q.qtype qclass = request.q.qclass key = (qname, qtype, qclass) if key in self.cache: self.logger.info( "Cached Request ({0:s}): {1:s} {2:s} {3:s}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname)) reply = request.reply() for rr in self.cache[key]: reply.add_answer(rr) self.fire(write(peer, reply.pack())) return if key in self.hosts: self.logger.info( "Local Hosts Request ({0:s}): {1:s} {2:s} {3:s}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname)) reply = request.reply() for rdata in self.hosts[key]: rr = RR(qname, rclass=CLASS.IN, rtype=QTYPE.AAAA if ":" in rdata else QTYPE.A, rdata=AAAA(rdata) if ":" in rdata else A(rdata)) reply.add_answer(rr) self.cache[key] = rr self.fire(write(peer, reply.pack())) return records = Record.objects.filter(rname=qname) if not records: self.logger.info( "Request ({0:s}): {1:s} {2:s} {3:s} -> {4:s}:{5:d}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname, self.forward, 53)) lookup = DNSRecord(q=DNSQuestion(qname, qtype, qclass)) id = lookup.header.id self.peers[id] = peer self.requests[id] = request self.fire(write((self.forward, 53), lookup.pack())) return self.logger.info( "Authoritative Request ({0:s}): {1:s} {2:s} {3:s}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname)) rr = [] reply = request.reply() if len(records) == 1 and records[0].rtype == CNAME: rr.append(records[0].rr) records = Record.objects.filter(rname=records[0].rdata) for record in records: rr.append(record.rr) reply.add_answer(*rr) self.cache[key] = rr self.fire(write(peer, 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
dhdr[f2] = o.header.a dhdr[f3] = o.header.ns dhdr[f4] = o.header.ar d['questions'] = [] for q in o.questions: dq = { 'qname': str(q.qname), 'qtype': QTYPE[q.qtype], 'qclass': QTYPE[q.qclass] } d['questions'].append(dq) d['rr'] = [] for r in o.rr: dr = { 'rname': str(r.rname), 'rtype': QTYPE.lookup(r.rtype, r.rtype), 'rclass': CLASS[r.rclass], 'ttl': r.ttl, 'rdata': str(r.rdata) } d['rr'].append(dr) d['timestamp'] = packet_timedate(udp.timestamp) d['src'] = src d['sport'] = sport d['dst'] = dst d['dport'] = dport if module_data['mongo']: module_data['db'].insert(d) chop.prnt(d)
def request(self, peer, request): qname = str(request.q.qname) qtype = request.q.qtype qclass = request.q.qclass key = (qname, qtype, qclass) if key in self.cache: self.logger.info( "Cached Request ({0:s}): {1:s} {2:s} {3:s}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname ) ) reply = request.reply() for rr in self.cache[key]: reply.add_answer(rr) self.fire(write(peer, reply.pack())) return if key in self.hosts: self.logger.info( "Local Hosts Request ({0:s}): {1:s} {2:s} {3:s}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname ) ) reply = request.reply() for rdata in self.hosts[key]: rr = RR( qname, rclass=CLASS.IN, rtype=QTYPE.AAAA if ":" in rdata else QTYPE.A, rdata=AAAA(rdata) if ":" in rdata else A(rdata) ) reply.add_answer(rr) self.cache[key] = rr self.fire(write(peer, reply.pack())) return records = Record.objects.filter(rname=qname) if not records: self.logger.info( "Request ({0:s}): {1:s} {2:s} {3:s} -> {4:s}:{5:d}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname, self.forward, 53 ) ) lookup = DNSRecord(q=DNSQuestion(qname, qtype, qclass)) id = lookup.header.id self.peers[id] = peer self.requests[id] = request self.fire(write((self.forward, 53), lookup.pack())) return self.logger.info( "Authoritative Request ({0:s}): {1:s} {2:s} {3:s}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname ) ) rr = [] reply = request.reply() if len(records) == 1 and records[0].rtype == CNAME: rr.append(records[0].rr) records = Record.objects.filter(rname=records[0].rdata) for record in records: rr.append(record.rr) reply.add_answer(*rr) self.cache[key] = rr self.fire(write(peer, reply.pack()))
def request(self, peer, request): qname = str(request.q.qname) qtype = request.q.qtype qclass = request.q.qclass key = (qname, qtype, qclass) if key in self.cache: self.logger.info( "Cached Request ({0:s}): {1:s} {2:s} {3:s}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname ) ) reply = request.reply() for rr in self.cache[key]: reply.add_answer(rr) self.fire(write(peer, reply.pack())) return if key in self.hosts: self.logger.info( "Local Hosts Request ({0:s}): {1:s} {2:s} {3:s}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname ) ) rr = [RR(qname, rdata=A(self.hosts[key]))] reply = request.reply() reply.add_answer(*rr) self.cache[key] = rr self.fire(write(peer, reply.pack())) return records = Record.objects.filter( rname=qname, rclass=qclass, rtype=qtype ) if records: self.logger.info( "Authoritative Request ({0:s}): {1:s} {2:s} {3:s}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname ) ) rr = [record.rr for record in records] reply = request.reply() reply.add_answer(*rr) self.cache[key] = rr self.fire(write(peer, reply.pack())) return self.logger.info( "Request ({0:s}): {1:s} {2:s} {3:s}".format( "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype), qname ) ) lookup = DNSRecord(q=DNSQuestion(qname, qtype, qclass)) id = lookup.header.id self.peers[id] = peer self.requests[id] = request self.fire(write((self.forward, 53), lookup.pack()))