Example #1
0
    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]
Example #2
0
    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]
Example #3
0
    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}")
Example #4
0
 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
Example #5
0
 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
Example #6
0
        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
Example #7
0
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)
Example #8
0
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
Example #9
0
    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
Example #10
0
    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
Example #11
0
        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
Example #12
0
    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)
Example #13
0
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)
Example #14
0
    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
Example #15
0
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()
Example #16
0
    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()))
Example #17
0
    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']:
Example #18
0
    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()))
Example #19
0
    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
Example #20
0
    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)
Example #21
0
    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()))
Example #22
0
    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()))