def _packetize_txt(self, query, response, opcode, data=None):
        """
        will break up the transmitted data into payloads that can be sent
        over the network. The size of the packets will be 255 - 3 for the
        header bytes needed to reassemble packets by resolution.
        :param query: A DNSRecord query
        :param response: A DNSRecord response skeleton made by doing query.reply()
        :param opcode: an integer representing the opcode for resolution to interpret
        :param data: the data to encode
        :return: a dnslib.DNSRecord with the first payload chunk and a deque() of next chunks
        to be sent
        """
        if not data:
            data = "010vsp1=This is a DNS TXT Record"

        self.prev_cmd = []
        rest = deque()
        _, constructor, msg_size = Records.TXT.value
        rr_type = query.questions[0].qtype
        chunks = [
            f"{data[i:i+msg_size]}" for i in range(0, len(data), msg_size)
        ]
        #self.logger.debug(chunks)
        for i, chunk in enumerate(chunks):
            answer = RR(rname=query.get_q().get_qname(),
                        rtype=rr_type,
                        rclass=CLASS.IN,
                        rdata=constructor(f"{opcode}{len(chunks)}{i}" + chunk),
                        ttl=1337)
            self.prev_cmd.append(answer)

            # Add at least one response to the query
            if i == 0:
                response.add_answer(answer)
                continue

            # If Extended DNS is enabled, we can have up to 2048 bytes.
            # Otherwise we're going to send command over multiple queries
            if self.edns and i > 0:
                response.add_answer(answer)
            else:
                rest.append(answer)

        if len(chunks) > 1:
            # Add the end transmission packet to signal that it is done
            rest.append(
                RR(rname=query.get_q().get_qname(),
                   rtype=rr_type,
                   rclass=CLASS.IN,
                   rdata=constructor("510END-TRANSMISSION"),
                   ttl=1337))
        return response, rest
def get_chromecast_mdns_response_2017_22(query_data, chromecast_ip, chromecast_uuid, friendly_name, bs):
    from dnslib import dns, RR, QTYPE, A, PTR, TXT, SRV
    # query_a = dns.DNSRecord.parse(query_data)
    query_a = query_data
    ans = query_a.reply(ra=0)
    ans.questions = []
    collapsed_uuid=chromecast_uuid.replace("-","")
    long_mdns_name = "Chromecast-%s._googlecast._tcp.local"%collapsed_uuid
    ans.add_answer(RR("_googlecast._tcp.local", QTYPE.PTR, rdata=PTR(long_mdns_name), ttl=120))
    ans.add_ar(RR(long_mdns_name, QTYPE.TXT, rdata=TXT(["id=%s"%collapsed_uuid, "rm=", "ve=05", "md=Chromecast", "ic=/setup/icon.png", "fn=%s"%friendly_name, "ca=4101", "st=0", "bs=%s"%bs, "rs="]), ttl=4500, rclass=32769))
    ans.add_ar(RR(long_mdns_name, QTYPE.SRV, rdata=SRV(0, 0, 8009, "%s.local"%chromecast_uuid), rclass=32769,ttl=120))
    ans.add_ar(RR("%s.local"%chromecast_uuid, QTYPE.A, rdata=A(chromecast_ip),rclass=32769,ttl=120))
    return [ans]
Exemple #3
0
 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:
             if ":" in addr:
                 reply.add_answer(
                     RR(rec.q.qname, QTYPE.AAAA, rdata=AAAA(addr)))
             else:
                 reply.add_answer(RR(rec.q.qname, QTYPE.A, rdata=A(addr)))
     return reply.pack()
    def resolve(self, request, handler):
        print(request.q.qname)

        if request.q.qname in self.blacklist:
            answer = RR(rdata=A(self.host))
            answer.set_rname(self.answer)
            reply = request.reply()
            reply.add_answer(answer)
            print(reply)
            print("-" * 200)
            return reply

        return ProxyResolver.resolve(self, request, handler)
Exemple #5
0
    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()
Exemple #6
0
    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)
Exemple #7
0
def gen_response(qt, qn):
    global serving_domains
    prefix_ = list(
        filter(lambda d: qn == d or qn.endswith('.' + d), serving_domains))
    if len(prefix_) != 1:
        # print("Error: invalid request domain {} in {}".format(qn, serving_domains))
        return None
    prefix = prefix_[0]
    print('REQ: ', qt, qn)

    if qt == 'SOA':
        generated_soa = dnslib.SOA(
            mname="todo." + domain_text,
            rname="*****@*****.**",
            times=(
                201307231,  # serial number
                10000,  # refresh
                2400,  # retry
                604800,  # expire
                3600,  # minimum
            ))
        return RR(rname=prefix,
                  rtype=QTYPE.SOA,
                  rclass=1,
                  ttl=86400,
                  rdata=generated_soa)
        # return {"mname": "todo."+domain_text, "rname": "*****@*****.**", "serial": "10", "refresh": 3600, "retry": 600, "expire": 604800, "minimum": 86400}
    elif qt == 'A':
        requested_ip = qn[:len(qn) - len(prefix)].strip('.')
        if not re.match(r'^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$', requested_ip):
            print("Invalid requested_ip: " + requested_ip)
            return None
        generated_a = dnslib.A(requested_ip)
        return RR(rname=qn,
                  rtype=QTYPE.A,
                  rclass=1,
                  ttl=86400,
                  rdata=generated_a)
    elif qt == 'NS':
        generated_ns = dnslib.NS(ns_ipaddr)
        return RR(rname=prefix,
                  rtype=QTYPE.NS,
                  rclass=1,
                  ttl=86400,
                  rdata=generated_ns)
    else:
        print("Invalid qt=" + qt)
        return None
Exemple #8
0
    def from_zone(cls, zone):
        records = []
        logger.info(f"loading zone: {zone.domain}/{zone.ip} ({zone.id})")
        dns_records = zone.dns_records or []
        # if the zone has no records, create some default ones
        if not dns_records:
            logger.warning(
                f"zone has no dns_records. loading defaults: {zone.domain}/{zone.ip} ({zone.id})"
            )
            rrs = RR.fromZone(
                ZONE_TEMPLATE.format(domain_name=zone.domain,
                                     domain_ip=zone.ip))
            zone_records = [Record.make(zone, rr) for rr in rrs]
            for zr in zone_records:
                # TODO: make this clean on output
                rrstr = str(dedent(str(zr.rr)))
                logger.debug(f"loading record entry: {rrstr}")
                logger.debug(
                    "loaded record details - name: {} | rtype: {} | rr: {}".
                    format(str(zr.rr.rname), str(QTYPE[zr.rr.rtype]),
                           str(zr.rr)))
        else:
            # loop over each dns_record of the zone and convert it to RR record
            dns_records = sorted(dns_records, key=lambda x: x.sort)
            zone_records = []
            for dns_record in dns_records:
                try:
                    rrs = RR.fromZone(dns_record.record)
                    _zone_records = [Record.make(zone, rr) for rr in rrs]
                    for zr in _zone_records:
                        rrstr = str(dedent(str(zr.rr)))
                        logger.debug(
                            f"loading record: {str(dns_record.record)}")
                        logger.debug(f"loading record entry: {rrstr}")
                        logger.debug(
                            "loaded record details - name: {} | rtype: {} | rr: {}"
                            .format(str(zr.rr.rname), str(QTYPE[zr.rr.rtype]),
                                    str(zr.rr)))
                    zone_records = zone_records + _zone_records
                except Exception as e:
                    logger.critical(
                        f'Error processing line ({e.__class__.__name__}: {e}) "{dns_record.id}:{dns_record.record}" '
                    )
                    raise e

        # add the records for the zone to the rest of the records
        records = records + zone_records
        return cls(records)
Exemple #9
0
    def _a_page_encoder(self, data, encoder, nonce):
        data = encoder.encode(data, nonce, symmetric=encoder.kex_completed)

        length = struct.pack('B', len(data))
        payload = length + data

        if len(payload) > 48:
            raise ValueError('Page size more than 45 bytes ({})'.format(
                len(payload)))

        response = []

        for idx, part in enumerate(
            [payload[i:i + 3] for i in xrange(0, len(payload), 3)]):
            header = (random.randint(1, 6) << 29)
            idx = idx << 25
            bits = (struct.unpack(
                '>I', '\x00' + part + chr(random.randrange(0, 255)) *
                (3 - len(part)))[0]) << 1
            packed = struct.unpack(
                '!BBBB',
                struct.pack('>I',
                            header | idx | bits | int(not bool(bits & 6))))
            address = '.'.join(['{}'.format(int(x)) for x in packed])
            response.append(RR('.', QTYPE.A, rdata=A(address), ttl=600))

        return response
Exemple #10
0
    def create_result(self, qname, qtype, value):
        """Create a result response for a question"""

        record_class = getattr(dnslib, qtype)
        return RR(rname=qname,
                  rtype=dnslib.QTYPE[qtype],
                  rdata=record_class(value))
Exemple #11
0
    def resolve(self, request, handler):
        reply = request.reply()
        zone = self.zones.get(request.q.qname)
        if zone is not None:
            for zone_records in zone:
                rr = zone_records.try_rr(request.q)
                rr and reply.add_answer(rr)
        else:
            # no direct zone so look for an SOA record for a higher level zone
            found = False
            for zone_label, zone_records in self.zones.items():
                if request.q.qname.matchSuffix(zone_label):
                    try:
                        soa_record = next(r for r in zone_records if r.is_soa)
                    except StopIteration:
                        continue
                    else:
                        reply.add_answer(soa_record.as_rr(zone_label))
                        found = True
                        break
            if not found:
                reply.add_answer(
                    RR(str(request.q.qname),
                       QTYPE.A,
                       rdata=A(
                           socket.gethostbyname_ex(str(
                               request.q.qname))[2][0]),
                       ttl=60))

        return reply
Exemple #12
0
    def resolve(self,request,handler):
        reply = request.reply()  # the object that this function will return in the end, with modifications
        qname = request.q.qname  # the domain that was looked up

        burrow_log("Request for " + str(DNSLabel(qname.label[-5:])), 0)

        # First, we make sure the domain ends in burrow.tech.
        # If not, we return an NXDOMAIN result.
        if not qname.matchSuffix("burrow.tech"):
            reply.header.rcode = RCODE.NXDOMAIN
            return reply
       
        # Next, we try to look up the domain in our list of fixed test records.
        found_fixed_rr = False
        for rr in self.fixedrrs:
            a = copy.copy(rr)
            if (a.rname == qname):
                found_fixed_rr = True
                LOG("Found a fixed record for " + str(a.rname))
                reply.add_answer(a)
        if found_fixed_rr:
            return reply

        # Alright, if we've gotten here it must be a Transmission API message!
        assert(not found_fixed_rr)
        response_dict = self.handle_transmission_api_message(qname)
        zone = generate_TXT_zone(str(qname), dict_to_attributes(response_dict))
        rrs = RR.fromZone(zone)
        for rr in rrs:
            reply.add_answer(rr)
        return reply
Exemple #13
0
    def resolve(self, request, handler):
        qname = request.q.qname
        qtype = QTYPE[request.q.qtype]

        qname = str(qname).split('.')
        if qname[-1] == '':
            qname.pop(-1)
        if qname[-1] == 'novalocal' and qtype in ['A', 'AAAA', 'MX']:
            reply = request.reply()
            servername = qname[-2]
            if len(qname) == 2:
                query = 'fixed'
            elif len(qname) == 3:
                query = qname[0]
            else:
                return reply
            if query not in ['fixed', 'floating']:
                return reply

            print(qname)
            for server in CachedNovaLookup.get_list():
                if server.name == servername:
                    for interface in server.addresses.values():
                        for ip in interface:
                            if ip['OS-EXT-IPS:type'] == query and qtype == 'A':
                                ans = RR.fromZone('{} 60 IN A {}'.format(
                                    request.q.qname, ip['addr']))[0]
                                print(ans)
                                ans.rname = request.q.qname
                                reply.add_answer(ans)

            return reply
        else:
            return super(NovaResolver, self).resolve(request, handler)
Exemple #14
0
    def resolve(self,request,handler):
        reply = request.reply()
        qname = request.q.qname
        # Format is 00.DATA.domain.tld'
        qstr = str(qname)
        label = qstr.split('.')

        if SYNTAX.match(qstr):
            chunk_id = int(label[0])
            chunk_data = label[1]
            if chunk_id not in self.chunks: self.chunks[chunk_id] = chunk_data

            # Decrypt and dump the chunk
            if len(self.chunks) == self.chunk_num:
                block = "".join([ self.chunks[i] for i in sorted(self.chunks.keys())]).decode('hex')
                plain = self.decrypt(block)
                try:
                    print('[+] %s: Credentials logged for user %s' % (time.ctime(), plain.split(':')[0]))
                    with open(self.out, 'ab') as o:
                        o.write('[%s] %s\n' % (time.ctime(), plain))
                except:
                    pass
                self.chunks.clear()

        reply.add_answer(RR(qname,QTYPE.TXT,ttl=self.ttl, rdata=TXT("x00x00x00x00x00")))
        return reply
Exemple #15
0
    def resolve(self, request, handler):
        type_name = QTYPE[request.q.qtype]
        reply = request.reply()
        for record in self.records:
            if record.match(request.q):
                reply.add_answer(record.rr)
        if reply.rr:
            logger.info('found zone for %s[%s], %d replies', request.q.qname,
                        type_name, len(reply.rr))
            return reply

        # no direct zone so look for an SOA record for a higher level zone
        for record in self.records:
            if record.sub_match(request.q):
                reply.add_answer(record.rr)

        if reply.rr:
            logger.info('found higher level SOA resource for %s[%s]',
                        request.q.qname, type_name)
            return reply

        logger.info('no local zone found, proxying %s[%s]', request.q.qname,
                    type_name)
        proxy_resp = super().resolve(request, handler)
        if type_name == 'A':
            if (self.check_block(proxy_resp.rr)):
                rr = RR(proxy_resp.rr[0].get_rname(),
                        request.q.qtype,
                        ttl=60,
                        rdata=A("127.0.0.1"))
                proxy_resp.rr = [rr]
                return proxy_resp
        return super().resolve(request, handler)
Exemple #16
0
    def _A(self, name):
        if name.label[0] == "data":
            print base64.b64decode(name.label[1]),
        else:
            print name

        return RR(name, QTYPE.A, rdata=A(IP_ADDRESS), ttl=0)
Exemple #17
0
    def resolve_mdns(self, request, handler, rewrite=None):

        sock = get_mdns_socket()
        d = DNSRecord(DNSHeader(id=0, bitmap=0), q=request.q)
        sock.sendto(d.pack(), (nameserver4, 5353))
        # sock.sendto(d.pack(), (nameserver6, 5353))
        qname = request.q.qname
        if rewrite:
            request.q.qname = rewrite
        reply = request.reply()

        while True:
            buf, remote = sock.recvfrom(8192)
            d = DNSRecord.parse(buf)
            success = False
            if (d.header.aa == 1) and (d.header.a > 0):
                for response in d.rr:
                    if str(response.rname) == qname:
                        success = True
                        response.rclass = CLASS.IN

                        # These two lines can be deleted if we dont want the original response
                        reply.add_answer(response)
                        response = RR.fromZone(response.toZone())[0]

                        if rewrite:
                            response.rname = rewrite
                            reply.add_answer(response)
                        # print(reply)
            if success:
                break
        return reply
Exemple #18
0
    def __init__(self, rname, rtype, args):
        self._rname = DNSLabel(rname)

        rd_cls, self._rtype = TYPE_LOOKUP[rtype]

        if self._rtype == QTYPE.SOA and len(args) == 2:
            # add sensible times to SOA
            args += (SERIAL_NO, 3600, 3600 * 3, 3600 * 24, 3600),

        if self._rtype == QTYPE.TXT and len(args) == 1 and isinstance(
                args[0], str) and len(args[0]) > 255:
            # wrap long TXT records as per dnslib's docs.
            args = wrap(args[0], 255),

        if self._rtype in (QTYPE.NS, QTYPE.SOA):
            ttl = 3600 * 24
        else:
            ttl = 300

        self.rr = RR(
            rname=self._rname,
            rtype=self._rtype,
            rdata=rd_cls(*args),
            ttl=ttl,
        )
    def resolve(self, request, handler):
        reply = request.reply()

        if request.q.qtype != QTYPE.A:
            log.error("Unsupported query qtype: `{}`".format(request.q.qtype))
            reply.header.rcode = getattr(RCODE, 'NXDOMAIN')
            return reply

        query = str(request.q.qname)
        if query not in self._records:
            log.error("qname `{}` not present in DB".format(query))
            reply.header.rcode = getattr(RCODE, 'NXDOMAIN')
            return reply

        log.info(
            "DNS query for `{}`, type `{}`, reply `{}`, ttl `{}`".format(
                query,
                request.q.qtype,
                self._records[query]['ip'],
                self._records[query]['ttl'])
        )

        reply.add_answer(
            *RR.fromZone("{} {} A {}".format(
                query,
                self._records[query]['ttl'],
                self._records[query]['ip'],
                )
            )
        )

        return reply
Exemple #20
0
    def resolve(self, request, handler):
        qname = request.q.qname
        qtype = QTYPE[request.q.qtype]

        # Custom answer only for A (ipv4) or ANY requests
        if fnmatch.fnmatch(str(qname), self.match) and qtype in ('A', 'ANY'):
            reply = request.reply()
            ip = self.get_ip_from_dns(str(qname))
            if len(ip) == 0:
                reply.header.rcode = getattr(RCODE, 'NXDOMAIN')
            else:
                reply.add_answer(RR(qname, QTYPE.A, rdata=A(ip), ttl=60))
            return reply
        try:
            if handler.protocol == 'udp':
                proxy_r = request.send(self.address,
                                       self.port,
                                       timeout=self.timeout)
            else:
                proxy_r = request.send(self.address,
                                       self.port,
                                       tcp=True,
                                       timeout=self.timeout)
            reply = DNSRecord.parse(proxy_r)
        except socket.timeout:
            reply = request.reply()
            reply.header.rcode = getattr(RCODE, 'NXDOMAIN')
        return reply
Exemple #21
0
 def __init__(self,zone=False):
     # add zone if supplied
     self.zone = []
     if zone:
         for rr in RR.fromZone(zone):
             if not self.exist(rr):
                 self.add_record(rr) 
Exemple #22
0
    def _resolve(self, request, handler):
        qname = request.q.qname
        reply = request.reply()

        # TODO:
        # Resolve NS?, DS, SOA somehow
        if not qname.matchSuffix(self.domain):
            if self.recursor:
                try:
                    return DNSRecord.parse(request.send(self.recursor, timeout=2))
                except socket.error:
                    pass
                except Exception as e:
                    logger.exception('DNS request forwarding failed ({})'.format(e))
            else:
                logger.debug('Bad domain: {} (suffix={})'.format(qname, self.domain))

            reply.header.rcode = RCODE.NXDOMAIN
            return reply


        arecords = self.process(qname.stripSuffix(self.domain).idna()[:-1])

        if arecords:
            for address in arecords:
                reply.add_answer(RR(qname, QTYPE.A, rdata=A(address), ttl=600))
        else:
            reply.header.rcode = RCODE.NXDOMAIN

        return reply
Exemple #23
0
 def resolve(self, request, handler):
     reply = request.reply()
     qname = request.q.qname
     cc_record = "in." + domain + "."
     qstr = str(qname)
     if cc_record in qstr:
         try:
             command_txt = q_commands.get(block=False, timeout=None)
         except queue.Empty:
             command_txt = ""
         reply.add_answer(*RR.fromZone(
             "{} 0 IN TXT \"{}\"".format(qname, base58.b58encode(command_txt.encode("utf-8")).decode("ascii"))))
     elif request.q.qtype == 1 and ("out." + domain + ".") in qstr:
         self.__parse_out(qstr)
         reply.add_answer(*RR.fromZone("{} 0 IN A {}".format(qname, "127.255.255.255")))
     return reply
def get_chromecast_mdns_response_2018_03(query_data, chromecast_ip, chromecast_uuid, friendly_name, bs, cd="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", rs="", ca=4101, st=0, nf=1):
    from dnslib import dns, RR, QTYPE, A, PTR, TXT, SRV
    query_a = query_data
    results = []

    collapsed_uuid=chromecast_uuid.replace("-","")
    long_mdns_name = "Chromecast-%s-1._googlecast._tcp.local"%collapsed_uuid
    for question in query_a.questions:
        ans = query_a.reply(ra=0)
        ans.questions = []
        ans.add_answer(RR(question.qname, QTYPE.PTR, rdata=PTR(long_mdns_name), ttl=120))
        ans.add_ar(RR(long_mdns_name, QTYPE.TXT, rdata=TXT(["id=%s"%collapsed_uuid, "cd=%s"%cd,"rm=", "ve=05", "md=Chromecast", "ic=/setup/icon.png", "fn=%s"%friendly_name, "ca=%s"%ca, "st=%s"%st, "bs=%s"%bs, "nf=%s"%nf,"rs=%s"%rs]), ttl=4500, rclass=32769))
        ans.add_ar(RR(long_mdns_name, QTYPE.SRV, rdata=SRV(0, 0, 8009, "%s.local"%chromecast_uuid), rclass=32769,ttl=120))
        ans.add_ar(RR("%s.local"%chromecast_uuid, QTYPE.A, rdata=A(chromecast_ip),rclass=32769,ttl=120))
        results.append(ans)
    return results
Exemple #25
0
 def respond(self, request):
     """Returns response containing self.ip."""
     address = str(request.questions[0].qname)
     self.logger.log(self.parseloglevel(), "{b} - Responding to request for address:'{addr}'".format(b=str(self), addr=address))
     response = request.reply()
     response.add_answer(RR(address, QTYPE.A, rdata=A(self.ip)))
     return response
Exemple #26
0
 def __init__(self,
              address,
              port,
              ttl,
              intercept,
              skip,
              nxdomain,
              timeout=0):
     """
         address/port    - upstream server
         ttl             - default ttl for intercept records
         intercept       - list of wildcard RRs to respond to (zone format)
         skip            - list of wildcard labels to skip 
         nxdomain        - list of wildcard labels to retudn NXDOMAIN
         timeout         - timeout for upstream server
     """
     self.address = address
     self.port = port
     self.ttl = parse_time(ttl)
     self.skip = skip
     self.nxdomain = nxdomain
     self.timeout = timeout
     self.zone = []
     for i in intercept:
         if i == '-':
             i = sys.stdin.read()
         for rr in RR.fromZone(i, ttl=self.ttl):
             self.zone.append((rr.rname, QTYPE[rr.rtype], rr))
Exemple #27
0
def DNSGuard(ip, port, blacklist):
    octetsize = 512
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind((ip, port))
    data = None
    addr = None
    R = resolver.Resolver()
    logging.debug("DNSGuard SERVER ACTIVE ON {}:{}".format(ip, port))
    while True:
        data, addr = sock.recvfrom(octetsize)
        packet = DNSRecord.parse(data)
        question = packet.get_q()
        fqdn = FQDN(question)
        logging.debug("Query: {}".format(str(packet)))
        if allowed(fqdn, blacklist):
            try:
                zones = R.resolveZone([fqdn])
                logging.debug("Allowed: {}".format(zones))
                reply = packet.reply()
                for zone in zones:
                    reply.add_answer(*RR.fromZone(zone))
                    sock.sendto(DNSRecord.pack(reply), addr)
            except Exception as e:
                logging.error("Error: {}".format(e))
            pass
    pass
Exemple #28
0
    def resolve_forward(self, qname, qtype, reply):
        """
        Build a response to a forward DNS query (i.e. one that contains a
        hostname)

        :param dnslib.DNSRecord qname: The query's target.
        :param str qtype: The type of query (e.g. ``"SRV"``)
        :param dnslib.DNSRecord reply: The DNSRecord to populate with the reply.
        """
        # Request isn't even in our domain
        if not qname.matchSuffix(self.domain):
            logging.warning("Rejecting query outside our domain: %s", qname)
            reply.header.rcode = RCODE.NOTAUTH
            return
        with self.lock:
            # Is the request for a service alias?
            for srv_domain, addrs in self.services.items():
                if qname.matchSuffix(srv_domain):
                    if not addrs:
                        if (time.time() - self._startup >
                                STARTUP_QUIET_PERIOD):
                            logging.warning(
                                "No instances found, returning "
                                "SERVFAIL for %s", qname)
                        # If there are no instances, we are unable to read from
                        # ZK (or else the relevant service is down), so return
                        # SERVFAIL
                        reply.header.rcode = RCODE.SERVFAIL
                        return
                    for addr in addrs:
                        reply.add_answer(RR(qname, QTYPE.A, rdata=A(addr)))
                    return
            logging.warning("Unknown service: %s", qname)
            reply.header.rcode = RCODE.NXDOMAIN
Exemple #29
0
 def __init__(self):
     fixed_zone = open("fixed_zone/primary.txt").read() + open("fixed_zone/tests.txt").read()
     self.fixedrrs = RR.fromZone(fixed_zone)
     self.active_transmissions = {}  # Dictionary of Transmission objects.
                                     # Their ID's are the keys, for easy/quick lookup.
     self.cache = ExpiringDict(max_len=100000, max_age_seconds=70)
     self.transmission_handler_lock = multiprocessing.Lock()
Exemple #30
0
    def resolve(self, request, handler):
        reply = request.reply(
        )  # the object that this function will return in the end, with modifications
        qname = request.q.qname  # the domain that was looked up

        burrow_log("Request for " + str(DNSLabel(qname.label[-5:])), 0)

        # First, we make sure the domain ends in burrow.tech.
        # If not, we return an NXDOMAIN result.
        if not qname.matchSuffix("burrow.tech"):
            reply.header.rcode = RCODE.NXDOMAIN
            return reply

        # Next, we try to look up the domain in our list of fixed test records.
        found_fixed_rr = False
        for rr in self.fixedrrs:
            a = copy.copy(rr)
            if (a.rname == qname):
                found_fixed_rr = True
                LOG("Found a fixed record for " + str(a.rname))
                reply.add_answer(a)
        if found_fixed_rr:
            return reply

        # Alright, if we've gotten here it must be a Transmission API message!
        assert (not found_fixed_rr)
        response_dict = self.handle_transmission_api_message(qname)
        zone = generate_TXT_zone(str(qname), dict_to_attributes(response_dict))
        rrs = RR.fromZone(zone)
        for rr in rrs:
            reply.add_answer(rr)
        return reply
Exemple #31
0
 def resolve(self, request, handler):
     """
     Respond to DNS request - parameters are request packet & handler.
     Method is expected to return DNS response
     """
     reply = request.reply()
     qname = request.q.qname
     qtype = QTYPE[request.q.qtype]
     if qtype == "TXT":
         txtpath = os.path.join(tempfile.gettempdir(), str(qname).lower())
         if os.path.isfile(txtpath):
             reply.add_answer(
                 RR(qname, QTYPE.TXT, rdata=TXT(open(txtpath).read().strip()))
             )
     for name, rtype, rr in self.zone:
         # Check if label & type match
         if getattr(qname, self.eq)(name) and (
             qtype == rtype or qtype == "ANY" or rtype == "CNAME"
         ):
             # If we have a glob match fix reply label
             if self.glob:
                 a = copy.copy(rr)
                 a.rname = qname
                 reply.add_answer(a)
             else:
                 reply.add_answer(rr)
             # Check for A/AAAA records associated with reply and
             # add in additional section
             if rtype in ["CNAME", "NS", "MX", "PTR"]:
                 for a_name, a_rtype, a_rr in self.zone:
                     if a_name == rr.rdata.label and a_rtype in ["A", "AAAA"]:
                         reply.add_ar(a_rr)
     if not reply.rr:
         reply.header.rcode = RCODE.NXDOMAIN
     return reply
Exemple #32
0
 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__()
Exemple #33
0
 def __init__(self,zone,glob=False):
     """
         Initialise resolver from zone file. 
         Stores RRs as a list of (label,type,rr) tuples
         If 'glob' is True use glob match against zone file 
     """
     self.zone = [(rr.rname,QTYPE[rr.rtype],rr) for rr in RR.fromZone(zone)]
     self.glob = glob
     self.eq = 'matchGlob' if glob else '__eq__'
Exemple #34
0
 def load_rules(cls, rules):
     for rule in rules:
         zone = None
         try:
             zone = RR.fromZone(rule)
         except Exception:
             print('[e] Malformed rule -- {rule}'.format(rule=rule))
             continue
         domain = rule.split()[0]
         cls._rules_tables[domain] = zone
Exemple #35
0
    def resolve(self, request, handler):
        db = Data()
        reply = request.reply()
        print(type(request))
        print('------------')
        #print(request.q)
        host = None
        ip = None
        for i in request.questions:
            host = i.qname
            ip = db.get_ip_by_host(host)
            print("Host {0} got ip {1}".format(host, ip))
            break

        print('------------')
        reply.add_answer(*RR.fromZone("{0} 60 A {1}".format(host, ip[0])))
        return reply
    def resolve(self,request,handler):
        reply = request.reply()
        qname = request.q.qname
        qtype = QTYPE[request.q.qtype]

        if qtype == 'SRV':
            port = 389
            if qname.label[0] == '_kpasswd':
                port = 464
            a = RR.fromZone('. 60 IN SRV 0 100 %d 192.168.0.1' % port)[0]
            a.rname = qname
            reply.add_answer(a)
        else:
            # Replace labels with request label
            for rr in self.rrs:
                a = copy.copy(rr)
                a.rname = qname
                reply.add_answer(a)
        return reply
Exemple #37
0
 def __init__(self, address, port, ttl, intercept, skip, nxdomain):
     """
         address/port    - upstream server
         ttl             - default ttl for intercept records
         intercept       - list of wildcard RRs to respond to (zone format)
         skip            - list of wildcard labels to skip
         nxdomain        - list of wildcard labels to retudn NXDOMAIN
     """
     self.address = address
     self.port = port
     self.ttl = parse_time(ttl)
     self.skip = skip
     self.nxdomain = nxdomain
     self.zone = []
     for i in intercept:
         if i == "-":
             i = sys.stdin.read()
         for rr in RR.fromZone(i, ttl=self.ttl):
             self.zone.append((rr.rname, QTYPE[rr.rtype], rr))
    def __init__(self, proxy=False, upstream=None):
        # Prepare the RRs
        self.rrs = RR.fromZone(LOCALHOST_ZONE)

        # Set which domain to serve
        self.domains = set()

        # Set the upstream DNS server
        if proxy and upstream:
            try:
                self.upstream, self.upstream_port = upstream.split(":")
                self.upstream_port = int(self.upstream_port)
            except ValueError:
                self.upstream = upstream
                self.upstream_port = 53
            finally:
                self.proxy = True
        else:
            self.proxy = False

        self.lock = threading.Lock()
Exemple #39
0
 def resolve(self,request,handler):
     client_ip = handler.client_address[0]
     #print "Request from IP: {}".format(client_ip)
     qname = request.q.qname
     qtype = QTYPE[request.q.qtype]
     reply = request.reply()
     self.log.debug("{} request for {} by {}".format(qtype,qname,client_ip))
     #print "query: {}".format(qname)
     #print "query: {}".format(qname.matchGlob("*.yahoo.com"))
     # Try to resolve locally unless on skip list
     rules = self.get_matching_rules(client_ip,qname)
     self.log.debug("Matched rules: {}".format(rules))
     if any(rules):
         ## Collecting info on match for logging
         match_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
         match_name = client_ip
         match_hosts = [h.name for h in self.hosts if h.ip == client_ip]
         if any(match_hosts):
             match_name = ",".join(match_hosts)
         for rule in rules:
             if rule.action == 'monitor':
                 monitor.info({'time':match_time,'match_name':match_name,'client_ip':client_ip,'qname':str(qname)})
             if rule.action == 'redirect':
                 self.log.debug( "[{}] REDIRECT {}-->{} to {}".format(match_time,match_name,qname,rule.redirect) )
                 redir = rule.redirect
                 reply.add_answer(*RR.fromZone("{} 3600 IN A {}".format(qname,redir)))
                 return reply
             if rule.action == 'block':
                 self.log.debug( "[{}] BLOCKED {}({})-->{}".format(match_time,match_name,client_ip,qname) )
                 return reply
             if rule.action == 'allow':
                 self.log.debug( "[{}] ALLOWED {}({})-->{}".format(match_time,match_name,client_ip,qname) )
     ## If no match or action == 'allow', then proxy the request to IP_UP
     if handler.protocol == 'udp':
         proxy_r = request.send(self.UP_IP,self.UP_PORT)
     else:
         proxy_r = request.send(self.UP_IP,self.UP_PORT,tcp=True)
     reply = DNSRecord.parse(proxy_r)
     return reply
Exemple #40
0
    def resolve(self, request, handler):
        reply = request.reply()

        # we handle A queries only
        if QTYPE[request.q.qtype] == 'A':
            # filter db for this domain
            domain = str(request.q.qname).rstrip('.')
            server = Server.objects.get_for_dns_or_none(domain=domain)
            if server:
                # add the answer to the request
                reply.add_answer(*RR.fromZone(
                    '{domain} {ttl} A {ip}'.format(
                        domain=domain,
                        ttl=300,
                        ip=server.ip
                    )
                ))

        # if there's no anser already, send query upstream
        if not reply.rr:
            proxy_r = request.send('8.8.8.8', 53)
            reply = DNSRecord.parse(proxy_r)

        return reply
Exemple #41
0
    def _resolve(self, request, handler):
        qname = request.q.qname
        reply = request.reply()

        # TODO:
        # Resolve NS?, DS, SOA somehow
        if not qname.matchSuffix(self.domain):
            if self.recursor:
                try:
                    return DNSRecord.parse(request.send(self.recursor, timeout=2))
                except socket.error:
                    pass
                except Exception as e:
                    logging.exception('DNS request forwarding failed')

            reply.header.rcode = RCODE.NXDOMAIN
            return reply

        responses = []

        session = None
        nonce = None

        try:
            request, session, nonce = self._q_page_decoder(qname)
            if session and session.last_nonce and session.last_qname:
                if nonce < session.last_nonce:
                    logging.info('Ignore nonce from past: {} < {}'.format(
                        nonce, session.last_nonce))
                    reply.header.rcode = RCODE.NXDOMAIN
                    return reply
                elif session.last_nonce == nonce and session.last_qname != qname:
                    logging.info('Last nonce but different qname: {} != {}'.format(
                        session.last_qname, qname))
                    reply.header.rcode = RCODE.NXDOMAIN
                    return reply

            for command in Parcel.unpack(request):
                for response in self._cmd_processor(command, session):
                    responses.append(response)

            if session:
                session.last_nonce = nonce
                session.last_qname = qname

        except DnsCommandServerException as e:
            nonce = e.nonce
            responses = [e.error, Policy(self.interval, self.kex), Poll()]

        except ParcelInvalidCrc as e:
            responses = [e.error]

        except DnsNoCommandServerException:
            reply.header.rcode = RCODE.NXDOMAIN
            return reply

        except DnsPingRequest, e:
            for i in xrange(e.args[0]):
                x = (i % 65536) >> 8
                y = i % 256
                a = RR('.', QTYPE.A, rdata=A('127.0.{}.{}'.format(x, y)), ttl=10)
                a.rname = qname
                reply.add_answer(a)

            return reply
Exemple #42
0
 def __init__(self,zone):
     # Parse RRs
     self.rrs = RR.fromZone(zone)
Exemple #43
0
 def load(self):
     logging.info("Loading DNS information from cloud providers")
     self.zone = [(rr.rname,QTYPE[rr.rtype],rr) for rr in RR.fromZone(self.zone_file_generator())]
Exemple #44
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()))
Exemple #45
-1
 def resolve(self, request, handler):
     reply = request.reply()
     domain = request.q.qname
     if request.q.qtype == QTYPE.TXT:  #acme server validates dns challenge
         reply.add_answer(
             RR(self.TXTrecord_domain,
                QTYPE.TXT,
                rdata=TXT(self.TXTrecord_data),
                ttl=100))
     else:
         reply.add_answer(
             RR(domain, QTYPE.A, rdata=A(self.address), ttl=100))
     #print("DNS SERVER REPLY: ",reply)
     return reply