Exemplo n.º 1
0
    def resolve(self, request, handler):
        global TXT_RECORDS
        reply = request.reply()
        name = request.q.qname
        logger.info("query %s", request.q.qname)

        # handle the main domain
        if (name == confs.BASE_DOMAIN
                or name == '_acme-challenge.' + confs.BASE_DOMAIN):
            r = RR(rname=request.q.qname,
                   rdata=dns.A(confs.LOCAL_IPV4),
                   rtype=QTYPE.A,
                   ttl=60 * 60)
            reply.add_answer(r)

            if self.SOA:
                r = RR(rname=request.q.qname,
                       rdata=self.SOA,
                       rtype=QTYPE.SOA,
                       ttl=60 * 60)
                reply.add_answer(r)

            if len(self.NS):
                for i in self.NS:
                    r = RR(rname=request.q.qname,
                           rdata=i,
                           rtype=QTYPE.NS,
                           ttl=60 * 60)
                    reply.add_answer(r)

            if confs.LOCAL_IPV6:
                r = RR(rname=request.q.qname,
                       rdata=dns.AAAA(confs.LOCAL_IPV6),
                       rtype=QTYPE.AAAA,
                       ttl=60 * 60)
                reply.add_answer(r)

            if len(TXT_RECORDS):
                r = RR(rname=request.q.qname,
                       rdata=dns.TXT([
                           '{1}'.format(k, v) for k, v in TXT_RECORDS.items()
                       ]),
                       rtype=QTYPE.TXT)
                reply.add_answer(r)
            return reply
        # handle subdomains
        elif name.matchSuffix(confs.BASE_DOMAIN):  # fnmatch
            labelstr = str(request.q.qname)
            logger.info("request: %s", labelstr)
            mv4 = re.match(
                '^([0-9]{1,3}-[0-9]{1,3}-[0-9]{1,3}-[0-9]{1,3})\.' +
                confs.BASE_DOMAIN + '\.$', labelstr)
            if mv4:
                ipv4 = mv4.group(1).replace('-', '.')

                # check if valid ip
                ipv4parts = [int(x) for x in ipv4.split('.')]
                if ((ipv4parts[0] == 192 and ipv4parts[1] == 168
                     and ipv4parts[2] == 0 and ipv4parts[3] <= 255)
                        or (ipv4parts[0] == 172 and 0 <= ipv4parts[1] <= 31
                            and ipv4parts[2] <= 255 and ipv4parts[3] <= 255)
                        or (ipv4parts[0] == 10 and 0 <= ipv4parts[1] <= 255
                            and ipv4parts[2] <= 255 and ipv4parts[3] <= 255)):
                    logger.info("ip is %s", ipv4)
                    r = RR(rname=request.q.qname,
                           rdata=dns.A(ipv4),
                           rtype=QTYPE.A,
                           ttl=24 * 60 * 60)
                    reply.add_answer(r)
                else:
                    logger.info('invalid ipv4 %s', labelstr)
            else:
                mv6 = re.match(
                    '^(fe80-[0-9a-f\-]{0,41})\.' + confs.BASE_DOMAIN + '\.$',
                    labelstr)
                if mv6:
                    ipv6 = mv6.group(1).replace('-', ':')
                    try:
                        ipaddress.ip_address(ipv6)  # validate IP
                        r = RR(rname=request.q.qname,
                               rdata=dns.AAAA(ipv6),
                               rtype=QTYPE.AAAA,
                               ttl=24 * 60 * 60)
                        reply.add_answer(r)
                    except:
                        # invalid ip
                        logger.info('invalid ipv6 %s', labelstr)
                        pass

            logger.info('found zone for %s, %d replies', request.q.qname,
                        len(reply.rr))
            return reply

        return super().resolve(request, handler)
Exemplo n.º 2
0
    def resolve(self, request, handler):
        global TXT_RECORDS
        reply = request.reply()
        name = request.q.qname
        logger.info("query %s", request.q.qname)

        # handle the main domain
        if (name == confs.BASE_DOMAIN
                or name == '_acme-challenge.' + confs.BASE_DOMAIN):
            r = RR(rname=request.q.qname,
                   rdata=dns.A(confs.LOCAL_IPV4),
                   rtype=QTYPE.A,
                   ttl=60 * 60)
            reply.add_answer(r)

            if self.SOA:
                r = RR(rname=request.q.qname,
                       rdata=self.SOA,
                       rtype=QTYPE.SOA,
                       ttl=60 * 60)
                reply.add_answer(r)

            if len(self.NS):
                for i in self.NS:
                    r = RR(rname=request.q.qname,
                           rdata=i,
                           rtype=QTYPE.NS,
                           ttl=60 * 60)
                    reply.add_answer(r)

            if confs.LOCAL_IPV6:
                r = RR(rname=request.q.qname,
                       rdata=dns.AAAA(confs.LOCAL_IPV6),
                       rtype=QTYPE.AAAA,
                       ttl=60 * 60)
                reply.add_answer(r)

            if len(TXT_RECORDS):
                r = RR(rname=request.q.qname,
                       rdata=dns.TXT([
                           '{1}'.format(k, v) for k, v in TXT_RECORDS.items()
                       ]),
                       rtype=QTYPE.TXT)
                reply.add_answer(r)
            return reply
        # handle subdomains
        elif name.matchSuffix(confs.BASE_DOMAIN):  # fnmatch
            labelstr = str(request.q.qname)
            logger.info("requestx: %s, %s", labelstr, confs.ONLY_PRIVATE_IPS)

            subdomains = labelstr.split('.')
            if len(subdomains) == 4:  # TODO: dynamic
                ip = None
                try:
                    ip = ipaddress.ip_address(subdomains[0].replace('-', '.'))
                except:
                    pass
                try:
                    if ip == None:
                        ip = ipaddress.ip_address(subdomains[0].replace(
                            '-', ':'))
                except:
                    logger.info('invalid ip %s', labelstr)
                    return reply

                # check if we only want private ips
                if not ip.is_private and confs.ONLY_PRIVATE_IPS:
                    return reply
                if ip.is_reserved and confs.NO_RESERVED_IPS:
                    return reply
                # check if it's a valid ip for a machine
                if ip.is_multicast or ip.is_unspecified:
                    return reply

                if type(ip) == ipaddress.IPv4Address:
                    ipv4 = subdomains[0].replace('-', '.')
                    logger.info("ip is ipv4 %s", ipv4)
                    r = RR(rname=request.q.qname,
                           rdata=dns.A(ipv4),
                           rtype=QTYPE.A,
                           ttl=24 * 60 * 60)
                    reply.add_answer(r)
                elif type(ip) == ipaddress.IPv6Address:
                    ipv6 = subdomains[0].replace('-', ':')
                    logger.info("ip is ipv6 %s", ipv6)
                    r = RR(rname=request.q.qname,
                           rdata=dns.AAAA(ipv6),
                           rtype=QTYPE.AAAA,
                           ttl=24 * 60 * 60)
                    reply.add_answer(r)
                else:
                    return reply

                logger.info('found zone for %s, %d replies', request.q.qname,
                            len(reply.rr))
            return reply
        elif self.address == "":
            return reply

        return super().resolve(request, handler)
Exemplo n.º 3
0
    def resolve(self, request, handler):

        domain_request = self.DOMAIN_REGEX.findall(str(request.q.qname))
        type_name = QTYPE[request.q.qtype]

        if not domain_request:
            return super().resolve(request, handler)

        domain_request = domain_request[0]

        packet_type = domain_request[0]
        db = sqlite3.connect('users.db')
        result = ""

        if packet_type == '0':
            cursor = db.cursor()
            cursor.execute(GET_MIN_ID)
            min_id = cursor.fetchone()[0]
            cursor.execute('''INSERT INTO users VALUES (?, ?, 'KEY')''',
                           (min_id, domain_request[8:-1]))
            db.commit()
            result = "{}{}".format(str(min_id).zfill(2), "KEY")
        elif packet_type == '1':
            id = domain_request[-3:-1]
            handler_client = proxy_handler.handlers[id]
            if handler_client['buffer'] is None:
                result = id + 'ND'
            else:
                b64 = base64.b64encode(
                    handler_client['buffer']).decode('utf-8')
                result = "{}{}:{}:{}".format(id, handler_client['target_ip'],
                                             handler_client['target_port'],
                                             b64)
                proxy_handler.handlers[id]['buffer'] = None
        elif packet_type == '2':
            req = self.PACKET_REGEX.findall(domain_request)
            if req:
                req = req[0]
                handler_client = proxy_handler.handlers[req[0]]
                handler_client['upstream_buffer'] += req[2].encode('utf-8')
                if req[1] != '000':
                    result = '{}{}:OK'.format(req[0], req[1])
                else:
                    handler_client['socket'].send(
                        base64.b64decode(handler_client['upstream_buffer']))
                    handler_client['upstream_buffer'] = b''
                    result = "ENDBLOCK"
            else:
                result = 'Error'

        elif packet_type == '3':
            id = domain_request[-3:-1]
            cursor = db.cursor()
            cursor.execute('''DELETE FROM users WHERE user_id = ?''', (id, ))
            db.commit()
            result = "{}REMOVED".format(id)

        reply = request.reply()
        reply.add_answer(
            RR(rname=DNSLabel(str(request.q.qname)),
               rtype=QTYPE.TXT,
               rdata=dns.TXT(wrap(result, 255)),
               ttl=300))

        db.close()

        if reply.rr:
            return reply