Пример #1
0
	def resolve(self, request, handler):
		reply = request.reply()
		
		# DNSLabel qname
		qname = request.q.qname

		if qname.matchSuffix("time.") or qname.matchSuffix("date."):
			utc_now = pytz.utc.localize(datetime.datetime.utcnow())
			try:
				timezone = str(qname)[:-6].replace('.', '/')
				tz_now = utc_now.astimezone(pytz.timezone(timezone))
			except pytz.UnknownTimeZoneError:
				reply.header.rcode = RCODE.REFUSED
				return reply
			
			if qname.matchSuffix("time."):
				reply.add_answer(RR(qname, QTYPE.A, ttl=0, rdata=A(tz_now.strftime("%H.%M.%S.0"))))
			elif qname.matchSuffix("date."):
				reply.add_answer(RR(qname, QTYPE.A, ttl=0, rdata=A(tz_now.strftime("%y.%m.%d.0"))))
				
			reply.add_answer(RR(qname, QTYPE.TXT, ttl=0, rdata=TXT(tz_now.strftime("%Y-%m-%d %H:%M:%S"))))
			reply.add_answer(RR(qname, QTYPE.AAAA, ttl=0, rdata=AAAA(tz_now.strftime("%Y:%m:%d::%H:%M:%S"))))
		
		elif qname.matchSuffix("md5."):
			md5 = hashlib.md5(str(qname.stripSuffix("md5."))[:-1])
			hash = str(md5.hexdigest())
			ipv6 = ':'.join([hash[i:i+4] for i in range(0, len(hash), 4)])
			reply.add_answer(RR(qname, QTYPE.AAAA, ttl=0, rdata=AAAA(ipv6)))
			reply.add_answer(RR(qname, QTYPE.TXT, ttl=0, rdata=TXT(hash)))
		
		if RR() == reply.get_a():
			reply.header.rcode = RCODE.NXDOMAIN
		return reply
Пример #2
0
def dns_handler(s, peer, data):
    request = DNSRecord.parse(data)
    id = request.header.id
    qname = request.q.qname
    qtype = request.q.qtype

    reply = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q)

    if "secsquare.herokuapp.com" == qname:
        # if the query is for SecSquare server
        reply.add_answer(RR(qname,qtype, rdata=A(SECSQUARE_HOST_ADDRESS)))
    else:
        # if query is for any other host names
        label = str(qname)
        raw_data = urllib2.urlopen("https://secsquare.herokuapp.com/api.php?name="+label).read()
        data = json.loads(raw_data)
        results = data['results']
        for entry in results:
            # put all results from SecSquare server into reply
            if 'MX' in entry['type']:
                reply.add_answer(RR(qname,qtype, rdata=MX(entry['target'])))
            elif 'AAAA' in entry['type']:
                reply.add_answer(RR(qname,qtype, rdata=AAAA(entry['ipv6'])))
            elif 'A' in entry['type']:
                reply.add_answer(RR(qname,qtype, rdata=A(entry['ip'])))
    print(reply) # print the DNS response for debugging purposes
    s.sendto(reply.pack(), peer)
Пример #3
0
	def resolve(self,request,handler):

		global dns_data
		global dns_reply

		reply = request.reply()
		qname = request.q.qname
		qname_str = str(qname)
		enc_data = qname_str.split('.')[0]
		data = decode_payload(enc_data)

		if request.q.qtype == QTYPE.A :		# The A version of the query
			# orig_response = gethostbyname()
			reply.add_answer(RR(qname,QTYPE.A,ttl=self.ttl,
								rdata=A('127.0.0.1')))

		if request.q.qtype == QTYPE.AAAA :		# The A version of the query
			if data :
				dns_data.put(data)

			try :
				data = dns_reply.get( False, 2 )
				dns_reply.task_done()
			except Exception as e :
				print "Sending Random data < for '%s'" % qname_str
				data = urandom(16)

			aaaa_repl = socket.inet_ntop(socket.AF_INET6, data)

			reply.add_answer(RR(qname,QTYPE.AAAA,ttl=self.ttl,
								rdata=AAAA(aaaa_repl)))
			# print reply

		# print "Replying to query for '%s" % qname_str
		return reply
Пример #4
0
 def resolve(self,request,handler):
     reply = request.reply()
     qtype = QTYPE[request.q.qtype]
     qname = request.q.qname
     # with 'exists:%{i}._ip.%{h}._domain.surfspf.net' in SPF-record of 'surf.nl'
     # mail from: '*****@*****.**' via 'outgoing2-ams.mf.surf.net' should result in a A-record query;
     # '145.0.1.5._ip.outgoing2-ams.mf.surf.net._helo.surf.nl._domain.surfspf.net.'
     if str(self.origin) in str(qname):
         if qtype == 'A':
             ip_version, ip_address = self.spfcheck(qname)
             if ip_version == -1:
                 reply.header.rcode = RCODE.SERVFAIL
             elif ip_version == 4:
                 reply.add_answer(RR(qname,QTYPE.A,ttl=self.ttl,
                                     rdata=A(ip_address)))
             elif ip_version == 6:
                 reply.add_answer(RR(qname,QTYPE.AAAA,ttl=self.ttl,
                                     rdata=AAAA(ip_address)))
             else:
                 reply.header.rcode = RCODE.NXDOMAIN
         else:
             reply.header.rcode = RCODE.NXDOMAIN
     else:
         reply.header.rcode = RCODE.REFUSED
     return reply
Пример #5
0
 def resolve(self, request, handler):
     print("resolver:" + "-" * 40)
     reply = request.reply()
     qname = request.q.qname
     ia = ip_address(handler.client_address[0])
     cmd = self.routes.get(qname)
     if cmd:
         output = getoutput(cmd).encode()
         reply.add_answer(
             RR(qname, QTYPE.TXT, ttl=self.ttl, rdata=TXT(output[:254])))
     else:
         rqt = QTYPE.TXT
         rqd = TXT(f"{str(ia)}")
         if request.q.qtype in [QTYPE.A, QTYPE.AAAA, QTYPE.PTR]:
             QTR = {QTYPE.A: "A", QTYPE.AAAA: "AAAA", QTYPE.PTR: "PTR"}
             qt = QTR[request.q.qtype]
             if ia.version is 6 and request.q.qtype == QTYPE.AAAA:
                 rqt = request.q.qtype
                 rqd = AAAA(str(ia))
             elif ia.version is 4 and request.q.qtype == QTYPE.A:
                 rqt = request.q.qtype
                 rqd = A(str(ia))
             elif request.q.qtype == QTYPE.PTR:
                 rqt = request.q.qtype
                 rqd = PTR(str(ia.reverse_pointer))
             else:
                 rqt = QTYPE.TXT
                 rqd = TXT(
                     f"Your request for {qt} confuses me, but here is the IP as text {str(ia)}"
                 )
         reply.add_answer(RR(qname, rqt, ttl=self.ttl, rdata=rqd))
     return reply
Пример #6
0
def dns_handler(s, peer, data):
    request = DNSRecord.parse(data)
    id = request.header.id
    qname = request.q.qname
    qtype = request.q.qtype
    print "------ Request (%s): %r (%s)" % (str(peer), qname.label,
                                            QTYPE[qtype])
    print request

    reply = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q)
    if qtype == QTYPE.A:
        reply.add_answer(RR(qname, qtype, rdata=A(IP)))
    if qtype == QTYPE.AAAA:
        reply.add_answer(RR(qname, qtype, rdata=AAAA(IPV6)))
    elif qtype == QTYPE['*']:
        reply.add_answer(RR(qname, QTYPE.A, rdata=A(IP)))
        reply.add_answer(RR(qname, QTYPE.MX, rdata=MX(IP)))
        reply.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(MSG)))
    else:
        reply.add_answer(RR(qname, QTYPE.CNAME, rdata=CNAME(MSG)))

    print "------ Reply"
    print reply

    s.sendto(reply.pack(), peer)
Пример #7
0
def test_hosts(client, watcher):
    client.fire(query("localhost"))
    assert watcher.wait("reply", "client")
    assert (set(map(attrgetter("rclass", "rtype", "rdata.data"),
                    client.a.rr)) == set([
                        (CLASS.IN, QTYPE.A, A("127.0.0.1").data),
                        (CLASS.IN, QTYPE.AAAA, AAAA("::1").data)
                    ]))
Пример #8
0
 def _validate_ips(self, ips):
     if not isinstance(ips, list):
         self._fail('Missing an "ips" array')
     for ip in ips:
         try:
             if ":" in ip:
                 ip = AAAA(ip)
             else:
                 ip = A(ip)
         except Exception, e:
             self._fail('Address parsing failed %s' % e)
Пример #9
0
    def parse_answer(self, raw_answer):
        # OUTPUT EXAMPLE:
        # {
        #     "Status": 0,
        #     "TC": false,
        #     "RD": true,
        #     "RA": true,
        #     "AD": false,
        #     "CD": false,
        #     "Question": [
        #         {
        #             "name": "google.ca.",
        #             "type": 255
        #         }
        #     ],
        #     "Answer": [
        #         {
        #             "name": "google.ca.",
        #             "type": 1,
        #             "TTL": 299,
        #             "data": "y.y.y.y"
        #         },...
        #     ],
        #     "Comment": "Response from x.x.x.x"
        # }

        d = self.dns_request.reply()
        dns_json_data = json.loads(raw_answer)
        if "Answer" in dns_json_data:
            for answer in dns_json_data["Answer"]:
                name = ""
                dns_type = 255
                ttl = 0
                data = ""
                for key, value in answer.items():
                    if key in "name":
                        name = value
                    elif key in "type":
                        dns_type = value
                    elif key in "TTL":
                        ttl = value
                    elif key in "data":
                        data = value
                if dns_type == QTYPE.A:
                    d.add_answer(RR(name, dns_type, ttl=ttl, rdata=A(data)))
                elif dns_type == QTYPE.AAAA:
                    d.add_answer(RR(name, dns_type, ttl=ttl, rdata=AAAA(data)))
                else:
                    logging.warning("+-------- DNS TYPE : " + str(dns_type) +
                                    " NOT SUPPORTED YET !")
        else:
            logging.info("+-------- OK - NO ANSWER FROM EXTERNAL DNS !!!")
        return d
Пример #10
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()
Пример #11
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)
Пример #12
0
def RecordFactory(qtype: str, data: str, logger: Any) -> Any:
    if qtype == "A":
        return A(data)
    elif qtype == "CNAME":
        return CNAME(data)
    elif qtype == "AAAA":
        return AAAA(data)
    elif qtype == "NS":
        return NS(data)
    elif qtype == "MX":
        pref, entry = data.split()
        print(pref, entry)
        return MX(preference=int(pref), label=entry)
    else:
        logger.error("not implemented query type")
Пример #13
0
def dns_handler(s, peer, data):
    request = DNSRecord.parse(data)
    id = request.header.id
    qname = request.q.qname
    qtype = request.q.qtype
    print "------ Request (%s): %r (%s)" % (str(peer), qname.label,
                                            QTYPE[qtype])
    print "\n".join(["  %s" % l for l in str(request).split("\n")])
    print ', '.join(str(x) for x in request.ar)

    def get_ecs_option(req):
        for record in request.ar:
            if type(record) is RR:
                for opt in record.rdata:
                    if type(opt) is EDNSOption:
                        if opt.code == 8:
                            return opt

    def ip_from_edns_subnet(req):
        opt = get_ecs_option(req)
        if opt is not None:
            data = opt.data[4:].ljust(4, '\0')
            data = socket.inet_ntoa(data)
            subnetlen = str(ord(opt.data[2]))
            print "Got ECS:", data, subnetlen
            return [data, data + "/" + subnetlen]
        return ["99.99.99.99", "0/0"]

    [IP, MSG] = ip_from_edns_subnet(request)

    reply = DNSRecord(DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q)
    if qtype == QTYPE.A:
        reply.add_answer(RR(qname, qtype, rdata=A(IP)))
    elif qtype == QTYPE.AAAA:
        reply.add_answer(RR(qname, qtype, rdata=AAAA(IPV6)))
    elif qtype == QTYPE['*']:
        reply.add_answer(RR(qname, QTYPE.A, rdata=A(IP)))
        reply.add_answer(RR(qname, QTYPE.MX, rdata=MX(IP)))
        reply.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(MSG)))
    else:
        reply.add_answer(RR(qname, QTYPE.CNAME, rdata=CNAME(MSG)))

    reply.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(MSG)))

    print "------ Reply"
    print "\n".join(["  %s" % l for l in str(reply).split("\n")])

    s.sendto(reply.pack(), peer)
Пример #14
0
    def resolve(self, request, handler):
        contract = w3.eth.contract(address=ROOT_RESOLVER_ADDRESS, abi=ABI)
        qname = request.q.qname
        labels = [label.decode('ascii') for label in qname.label]
        reply = request.reply()
        ip = None
        labels_hash = SHA256.new()
        for label in labels:
            labels_hash.update(label.encode('ascii'))
        labels_hash = labels_hash.digest()
        if labels_hash in mapping:
            ip = mapping[labels_hash]
        elif labels[len(labels) - 1] == 'hyperboria':
            while not ip:
                if labels:
                    label = str(labels.pop())
                elif label:
                    label = '.'
                else:
                    break
                if contract.functions.useResolver(_subdomain=label).call():
                    new_address = contract.functions.getResolver(
                        _subdomain=label).call()[0]
                    print(
                        'redirecting query to address {}'.format(new_address))
                    contract = w3.eth.contract(address=new_address, abi=ABI)
                else:
                    ip_data = contract.functions.resolveName(
                        _subdomain=label).call()
                    if not ip_data[2]:
                        break
                    ip = ip_data[0]
        if ip:
            try:
                ipaddress.ip_address(ip)
            except Exception as exc:
                print(repr(exc))
                reply.header.rcode = RCODE.NXDOMAIN
                return reply

            print("Name {} found: ip is {}".format('.'.join(labels), ip))
            reply.add_answer(RR(qname, QTYPE.AAAA, ttl=1, rdata=AAAA(ip)))
            mapping[labels_hash] = ip
            return reply
        else:
            proxy_r = request.send('8.8.8.8', 53)
            return DNSRecord.parse(proxy_r)
Пример #15
0
    def on_udp_query(self, req_data, addr):
        start_time = time.time()
        try:
            request = DNSRecord.parse(req_data)
            if len(request.questions) != 1:
                xlog.warn("query num:%d %s", len(request.questions), request)
                return

            domain = str(request.questions[0].qname)

            type = request.questions[0].qtype
            if type not in [1, 28]:
                xlog.warn("query:%s type:%d", domain, type)

            # xlog.debug("DNS query:%s type:%d from %s", domain, type, addr)

            ips = self.query(domain, type)

            reply = DNSRecord(DNSHeader(id=request.header.id,
                                        qr=1,
                                        aa=1,
                                        ra=1,
                                        auth=1),
                              q=request.q)
            for ip_cn in ips:
                ipcn_p = ip_cn.split("|")
                ip = ipcn_p[0]
                if "." in ip and type == 1:
                    reply.add_answer(RR(domain, ttl=60, rdata=A(ip)))
                elif ":" in ip and type == 28:
                    reply.add_answer(
                        RR(domain, rtype=type, ttl=60, rdata=AAAA(ip)))
            res_data = reply.pack()

            self.serverSock.sendto(res_data, addr)
            xlog.debug("query:%s type:%d from:%s, return ip num:%d cost:%d",
                       domain, type, addr, len(reply.rr),
                       (time.time() - start_time) * 1000)
        except Exception as e:
            xlog.exception("on_query except:%r", e)
Пример #16
0
    def query(self, peer, request):
        id = request.header.id
        qname = request.q.qname
        queryType = request.q.qtype
        reply = DNSRecord( DNSHeader(id=id, qr=1, aa=1, ra=1), q=request.q )

        def cnameRecursion(dHost):
            global tmpRes # used for overwriting previous recursion value
            tmpData = dbTest(dHost)
            # First: get CNAME of desired host
            cnameAddress = [i[1] for i in tmpData if i[0] == 'CNAME']
            tmpRes = (dHost,tmpData)
            if cnameAddress:
                newAddr = checkMacro(queryType,cnameAddress[0],dHost,peer)
                reply.add_answer(RR(dHost, QTYPE.CNAME, rdata=CNAME(newAddr)))
                # Second: get desired QTYPE from desired host
                printOut(peer,QTYPE.CNAME,str(dHost),newAddr)
                cnameRecursion(newAddr)
            return tmpRes

        qname,rData = cnameRecursion(qname)

        if queryType == QTYPE.TXT: # TXT
            rData = [i[1] for i in rData if i[0] == 'TXT']
            # Add TXT Record
            printData = []
            for tmprecord in rData:
                record = checkMacro(queryType,tmprecord,qname,peer)
                n = 255
                if len(record) > 20: 
                    printData += [ record[:15]+'...(%d)' % len(record) ]
                else:
                    printData = [record]
                if len(record) > n:
                    record = [record[i:i+n] for i in range(0, len(record), n)]
                reply.add_answer(RR(qname, QTYPE.TXT, rdata=TXT(record if isinstance(record,list) else [record,])))
            printOut(peer,queryType,str(qname),printData)

        elif queryType == QTYPE.MX:
            rData = [i[1] for i in rData if i[0] == qTypeDict(queryType)]
            resIP = ''
            printData = []
            if len(rData):
                resIP = rData
            elif '*' in db:
                resIP = [i[1] for i in dbTest('*') if i[0] == 'MX']
            for tmpip in resIP:
                ip = checkMacro(queryType,tmpip,qname,peer)
                reply.add_answer(RR(qname, QTYPE.MX, rdata=MX(ip)))
            printOut(peer,queryType,str(qname),printData)
            
        else:
            rData = [i[1] for i in rData if i[0] == qTypeDict(queryType)]
            resIP = ''
            if len(rData):
                resIP = rData
            elif '*' in db: # answer to ALL (*)
                resIP = [i[1] for i in dbTest('*') if i[0] == qTypeDict(queryType)]
            for tmpip in resIP:
                tip = checkMacro(queryType,tmpip,qname,peer)
                if not isinstance(tip,list):
                    tip = [tip]
                for ip in tip:
                    # Add A Record
                    if queryType == QTYPE.NS:
                        reply.add_answer(RR(qname, QTYPE.NS, rdata=NS(ip)))
                    elif queryType == QTYPE.AAAA:
                        if isValidIP(ip):
                            reply.add_answer(RR(qname, QTYPE.AAAA, rdata=AAAA(ip)))
                        else:
                            # Handle invalid IPv6, encode it in hex and send in form of IPv6
                            # Converting 'simpletext' -> ::7369:6d70:6c65:7465:7874
                            # To be used in 'file' macro
                            print("Invalid IPv6 provided: {!r}... Answering as HEX -> IPv6".format(ip[:20]))
                            n = 16
                            # if len(ip) > n:
                            if isinstance(ip,str):
                                ip = ip.encode()
                            record = [longToIP(int((ip[i:i+n]).hex(),16)) for i in range(0, len(ip), n)]
                            for i in record:
                                reply.add_answer(RR(qname, QTYPE.AAAA, rdata=AAAA(i)))
                    else:
                        reply.add_answer(RR(qname, QTYPE.A, rdata=A(ip), ttl=30))
            if resIP: 
                printOut(peer,queryType,str(qname),', '.join(resIP))
            else:
                printOut(peer,queryType,str(qname),'NONE')

        # Send To Client
        self.fire(write(peer, reply.pack()))
Пример #17
0
    async def dns_response(self, data):
        try:
            request = DNSRecord.parse(data)
            IPs = [MX(D.mail), soa_record] + ns_records
            ipv4_count = 0
            ipv6_count = 0
            if request.q.qtype == 1:
                ipv4_count = 32
            elif request.q.qtype == 28:
                ipv6_count = 32
            elif request.q.qtype == 255:
                ipv4_count = 16
                ipv6_count = 16
            else:
                ipv4_count = 32
            peers = await self.get_peers_to_respond(ipv4_count, ipv6_count)
            if len(peers) == 0:
                return None
            for peer in peers:
                ipv4 = True
                try:
                    _ = ipaddress.IPv4Address(peer)
                except ValueError:
                    ipv4 = False
                if ipv4:
                    IPs.append(A(peer))
                else:
                    try:
                        _ = ipaddress.IPv6Address(peer)
                    except ValueError:
                        continue
                    IPs.append(AAAA(peer))
            reply = DNSRecord(DNSHeader(id=request.header.id,
                                        qr=1,
                                        aa=len(IPs),
                                        ra=1),
                              q=request.q)

            records = {
                D: IPs,
                D.ns1: [
                    A(IP)
                ],  # MX and NS records must never point to a CNAME alias (RFC 2181 section 10.3)
                D.ns2: [A(IP)],
                D.mail: [A(IP)],
                D.andrei: [CNAME(D)],
            }

            qname = request.q.qname
            qn = str(qname)
            qtype = request.q.qtype
            qt = QTYPE[qtype]
            if qn == D or qn.endswith("." + D):
                for name, rrs in records.items():
                    if name == qn:
                        for rdata in rrs:
                            rqt = rdata.__class__.__name__
                            if qt in ["*", rqt
                                      ] or (qt == "ANY" and
                                            (rqt == "A" or rqt == "AAAA")):
                                reply.add_answer(
                                    RR(rname=qname,
                                       rtype=getattr(QTYPE, rqt),
                                       rclass=1,
                                       ttl=TTL,
                                       rdata=rdata))

                for rdata in ns_records:
                    reply.add_ar(
                        RR(rname=D,
                           rtype=QTYPE.NS,
                           rclass=1,
                           ttl=TTL,
                           rdata=rdata))

                reply.add_auth(
                    RR(rname=D,
                       rtype=QTYPE.SOA,
                       rclass=1,
                       ttl=TTL,
                       rdata=soa_record))

            return reply.pack()
        except Exception as e:
            log.error(f"Exception: {e}. Traceback: {traceback.format_exc()}.")
Пример #18
0
    def resolve(self, request, handler):
        reply = request.reply()
        qname = request.q.qname

        suffix = DNSLabel(self.origin)
        if str(qname.label[-len(suffix.label):]).lower() == str(suffix.label).lower():
            rem = DNSLabel(qname.label[:-len(suffix.label)])
            print(rem)

            found_rrs = []
            found_glob = []
            rrs = []
            for extra in ZoneExtra.objects.all():
                rrs += RR.fromZone(extra.entry)
            for dyn in DynamicEntry.objects.all():
                rrs += RR.fromZone(dyn.combined)
            for rr in rrs:
                if rem.matchSuffix(rr.rname):
                    rr.rname.label += self.origin.label
                    found_rrs.append(rr)
                elif rem.matchGlob(rr.rname):
                    rr.rname.label += self.origin.label
                    found_glob.append(rr)


            if len(found_rrs):
                reply.add_auth(*RR.fromZone(f"{self.origin} 60 IN NS {settings.DNS_BASE_DOMAIN}"))
                reply.add_answer(*found_rrs)
            elif len(found_glob):
                reply.add_auth(*RR.fromZone(f"{self.origin} 60 IN NS {settings.DNS_BASE_DOMAIN}"))
                for g in found_glob:
                    g.set_rname(qname)
                reply.add_answer(*found_glob)

            cts = Container.objects.filter(name=str(str(rem)[:-1]).lower())
            if cts.exists():
                ct = cts.first()
                reply.add_auth(*RR.fromZone(f"{self.origin} 60 IN NS {settings.DNS_BASE_DOMAIN}"))

                if request.q.qtype == QTYPE.A:
                    for ip in ct.ip_set.all():
                        if ip.is_ipv4:
                            reply.add_answer(RR(qname, QTYPE.A, ttl=self.ttl,
                                                rdata=A(ip.ip)))
                        elif ip.siit_ip.exists():
                            reply.add_answer(RR(qname, QTYPE.A, ttl=self.ttl,
                                                rdata=A(ip.siit_ip.first().ip)))
                if request.q.qtype == QTYPE.AAAA:
                    for ip in ct.ip_set.all():
                        if not ip.is_ipv4:
                            reply.add_answer(RR(qname, QTYPE.AAAA, ttl=self.ttl,
                                                rdata=AAAA(ip.ip)))
            # try other server
            if len(reply.rr) == 0 and (settings.DNS_MIRROR_SERVER is not None):
                print("checking other server because no rr and env: .%s. "%settings.DNS_MIRROR_SERVER)
                connections.close_all()  # might fail
                apk = request.send(settings.DNS_MIRROR_SERVER, 53, timeout=30)
                reply = DNSRecord.parse(apk)

            if len(reply.rr) == 0:
                reply.header.rcode = RCODE.NOERROR
        else:
            reply.header.rcode = RCODE.NXDOMAIN

        connections.close_all()
        return reply
Пример #19
0
def module_pack(txn, txndata):
    # logger.debug("response module pack")

    sharedData = txn.data()
    req = DNSRecord.parse(sharedData.rawRequest)
    answer = req.reply()
    question = sharedData.question
    qtype = QTYPE[req.q.qtype]

    module_counter = metrics.module()
    qtype_counter = metrics.qtype(qtype)

    client = txn.client()
    peerName = client.name()
    peerPort = client.port()
    peerType = client.typeName()

    # Assemble response
    if txn.status() != Txn.TXN_OK:
        logger.error(
            'ModulePack',
            'no answer for question: {} ,Peer: {}:{} {} ,type: {}'.format(
                question, peerName, peerPort, peerType,
                qtype), 'Please check previous errors/exceptions')

        # Increase error counter
        module_counter.error.inc(1)
        qtype_counter.error.inc(1)
    else:
        # Assemble DNS response
        nRawRecords = len(sharedData.record)
        nAnswers = len(sharedData.rankingRecord)
        nFiltered = nRawRecords - nAnswers
        ips = []

        for record in sharedData.rankingRecord:
            if req.q.qtype == QTYPE.A:
                answer.add_answer(
                    RR(question,
                       req.q.qtype,
                       rdata=A(record.ip),
                       ttl=record.ttl))
            elif req.q.qtype == QTYPE.AAAA:
                answer.add_answer(
                    RR(question,
                       req.q.qtype,
                       rdata=AAAA(record.ip),
                       ttl=record.ttl))

            ips.append((record.ip, record.ttl))

        # Increase response counter
        module_counter.response.inc(1)
        module_counter.total_records.inc(nAnswers)
        module_counter.total_filtered.inc(nFiltered)

        qtype_counter.response.inc(1)
        qtype_counter.total_records.inc(nAnswers)
        qtype_counter.total_filtered.inc(nFiltered)

        duration = (time.time() - sharedData.startTime) * 1000
        logger.info(
            'ModulePack',
            'Peer: {}:{} {} ,Duration: {:.3f} ms ,filtered: {} ,Question: {} '
            ',type: {}, {} Answers: {}'.format(peerName, peerPort, peerType,
                                               duration, nFiltered, question,
                                               qtype, nAnswers, ips))

    txndata.append(bytes(answer.pack()))
Пример #20
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()))
Пример #21
0
from dnslib import CLASS, RR, QTYPE, A, AAAA

mdns_domain = '.local.'

forward_dns_host = '1.1.1.1'
forward_dns_port = 53
forward_dns_tcp = False

static_entries = {
    'my.server.example.': [
        RR("my.server.example.",
           QTYPE.A,
           CLASS.IN,
           ttl=0,
           rdata=A('127.0.0.1')),
        RR("my.server.example.",
           QTYPE.AAAA,
           CLASS.IN,
           ttl=0,
           rdata=AAAA('fe80::1')),
    ]
}
Пример #22
0
    def resolve(self, request, handler):
        reply = request.reply()

        # IP of inbound DNS request
        yourip = ipaddress.ip_address(unicode(handler.client_address[0]))

        # Wildcards if the --host supplied is 'any', otherwise limits to predefined --host
        if str(self.host).lower() == "any":
            hostname = str(request.q.qname)
        else:
            hostname = self.host

        # Build standard record contents for reply
        # e.g. local.test.	60	IN	SOA	ns1.local.test. hostmaster.local.test. 1 3600 600 604800 60
        soar = SOA("ns1." + hostname,
                   "hostmaster." + hostname,
                   (1, 3600, 600, 604800, 60))
        # e.g. local.test.	60	IN	NS	ns1.local.test.
        #      local.test.	60	IN	NS	ns2.local.test.
        ns1r = NS("ns1." + hostname)
        ns2r = NS("ns2." + hostname)

        """
        Request construction
          Verify that the request is valid, which records were requested, and construct the response
          Uses add_answer for Answer and add_auth for Authority response sections
        """

        # Matching hostname or --host 'any' was used
        if request.q.qname == hostname:

            # A record
            if QTYPE[request.q.qtype] == "A":
                # If A was requested but inbound is v6, return SOA with NOERROR ("no problem but nothing found")
                if type(yourip) == ipaddress.IPv6Address:
                    reply.add_auth(RR(
                        hostname,
                        QTYPE.SOA,
                        rdata=soar,
                        ttl=60))
                    reply.header.rcode = RCODE.NOERROR
                # Otherwise return NS1, NS2, and A
                else:
                    reply.add_auth(RR(
                        hostname,
                        QTYPE.NS,
                        rdata=ns1r,
                        ttl=60))
                    reply.add_auth(RR(
                        hostname,
                        QTYPE.NS,
                        rdata=ns2r,
                        ttl=60))
                    reply.add_answer(RR(
                        hostname,
                        QTYPE.A,
                        rdata=A(str(yourip)),
                        ttl=60))

            # AAAA record
            elif QTYPE[request.q.qtype] == "AAAA":
                # If AAAA was requested but inbound is v4, return SOA with NOERROR ("no problem but nothing found")
                if type(yourip) == ipaddress.IPv4Address:
                    reply.add_auth(RR(
                        hostname,
                        QTYPE.SOA,
                        rdata=soar,
                        ttl=60))
                    reply.header.rcode = RCODE.NOERROR
                # Otherwise return NS1, NS2, and AAAA
                else:
                    reply.add_auth(RR(
                        hostname,
                        QTYPE.NS,
                        rdata=ns1r,
                        ttl=60))
                    reply.add_auth(RR(
                        hostname,
                        QTYPE.NS,
                        rdata=ns2r,
                        ttl=60))
                    reply.add_answer(RR(
                        hostname,
                        QTYPE.A,
                        rdata=AAAA(str(yourip)),
                        ttl=60))

            # TXT record
            #   Return NS1, NS2, and human-formatted TXT with IP address
            elif QTYPE[request.q.qtype] == "TXT":
                reply.add_auth(RR(
                    hostname,
                    QTYPE.NS,
                    rdata=ns1r,
                    ttl=60))   
                reply.add_auth(RR(
                    hostname,
                    QTYPE.NS,
                    rdata=ns2r,
                    ttl=60))
                reply.add_answer(RR(
                    hostname,
                    QTYPE.TXT,
                    rdata=TXT("Your IP is " + str(yourip)),
                    ttl=60))
            
            # NS record
            #   Return just NS1 and NS2
            elif QTYPE[request.q.qtype] == "NS":
                reply.add_answer(RR(
                    hostname,
                    QTYPE.NS,
                    rdata=ns1r,
                    ttl=43200))
                reply.add_answer(RR(
                    hostname,
                    QTYPE.NS,
                    rdata=ns2r,
                    ttl=43200))

            # SOA record
            #   Return just SOA
            elif QTYPE[request.q.qtype] == "SOA":
                reply.add_answer(RR(
                    hostname,
                    QTYPE.SOA,
                    rdata=soar,
                    ttl=60))

            # ANY record
            #   Returns A/AAAA, TXT, NS1, NS2, and SOA
            elif QTYPE[request.q.qtype] == "ANY":
                # AAAA for IPv6
                if type(yourip) == ipaddress.IPv6Address:
                    reply.add_answer(RR(
                        hostname,
                        QTYPE.A,
                        rdata=AAAA(str(yourip)),
                        ttl=60))
                # A for IPv4
                else:
                    reply.add_answer(RR(
                        hostname,
                        QTYPE.A,
                        rdata=A(str(yourip)),
                        ttl=60))
                # TXT
                reply.add_answer(RR(
                    hostname,
                    QTYPE.TXT,
                    rdata=TXT("Your IP is " + str(yourip)),
                    ttl=60))
                # NS1
                reply.add_answer(RR(
                    hostname,
                    QTYPE.NS,
                    rdata=ns1r,
                    ttl=60))
                # NS2
                reply.add_answer(RR(
                    hostname,
                    QTYPE.NS,
                    rdata=ns2r,
                    ttl=60))
                # SOA
                reply.add_answer(RR(
                    hostname,
                    QTYPE.SOA,
                    rdata=soar,
                    ttl=60))

            # All other types are invalid, e.g. MX or CNAME;
            #   Return only SOA and NOERROR ("no problem but nothing found")
            else:
                reply.add_auth(RR(
                    hostname,
                    QTYPE.SOA,
                    rdata=soar,
                    ttl=60))
                reply.header.rcode = RCODE.NOERROR

	# Respond with appropriate rset for NS1.hostname.tld (A/IPv4 only)
	#   Skipped for --host any, since we'd just use the same IP for NS1/NS2 anyway
        elif request.q.qname == "ns1." + hostname:
            # Only respond for A records, all others receive SOA and NOERROR ("no problem but nothing found")
            if QTYPE[request.q.qtype] == "A":
                reply.add_auth(RR(
                    hostname,
                    QTYPE.NS,
                    rdata=ns1r,
                    ttl=60))   
                reply.add_auth(RR(
                    hostname,
                    QTYPE.NS,
                    rdata=ns2r,
                    ttl=60))   
                reply.add_answer(RR(
                    "ns1." + hostname,
                    QTYPE.A,
                    rdata=A(myip),
                    ttl=60))
            else:
                reply.add_auth(RR(
                    hostname,
                    QTYPE.SOA,
                    rdata=soar,
                    ttl=60))   
                reply.header.rcode = RCODE.NOERROR

        # NS2.hostname.tld (A only)
        elif request.q.qname == "ns2." + hostname:
            # Only respond for A records, all others receive SOA and NOERROR ("no problem but nothing found")
            if QTYPE[request.q.qtype] == "A":
                reply.add_auth(RR(
                    hostname,
                    QTYPE.NS,
                    rdata=ns1r,
                    ttl=60))   
                reply.add_auth(RR(
                    hostname,
                    QTYPE.NS,
                    rdata=ns2r,
                    ttl=60))   
                reply.add_answer(RR(
                    "ns2." + hostname,
                    QTYPE.A,
                    rdata=A(myip),
                    ttl=60))
            else:
                reply.add_auth(RR(
                    hostname,
                    QTYPE.SOA,
                    rdata=soar,
                    ttl=60))
                reply.header.rcode = RCODE.NOERROR

        # Invalid host, correct domain? NXDOMAIN
        elif hostname in str(request.q.qname):
            reply.header.rcode = RCODE.NXDOMAIN
            reply.add_auth(RR(
                hostname,
                QTYPE.SOA,
                rdata=soar,   
                ttl=60))  
        
        # Invalid domain without --host any? REFUSED
        else:
            reply.header.rcode = RCODE.REFUSED

        # Return constructed rrset
        return reply