Beispiel #1
0
def prepare_reply(answer, request):
    #pack anwsers
    qname = request.q.qname
    qtype = request.q.qtype
    qt = dnslib.QTYPE[qtype]
    rcode = 0

    reply = dnslib.DNSRecord(\
                dnslib.DNSHeader(id=request.header.id, qr=1, aa=1, ra=1),\
                                 q=request.q)
    bad_reply = dnslib.DNSRecord(dnslib.DNSHeader(\
                            id=request.header.id, qr=1, aa=1, ra=1,\
                            rcode=rcode), q=request.q)

    record_class = getattr(dnslib, str(qt))
    empty_ans = True
    if rcode == 0:
        rcode = answer[1]
    for a in answer[0]:
        empty_ans = False
        reply.add_answer(dnslib.RR(rname=qname, rtype=qtype,\
                     rclass=1, ttl=10, rdata=record_class(a)))

    #print "---- Reply:\n", reply
    # if failed, send back error code
    if empty_ans and rcode > 0:
        reply = bad_reply

    return reply.pack()
Beispiel #2
0
 def get_reply_record(self, data):
     request = dnslib.DNSRecord.parse(data)
     qname = str(request.q.qname).lower()
     qtype = request.q.qtype
     dnsservers = self.dns_servers
     if qname.endswith('.in-addr.arpa'):
         ipaddr = '.'.join(reversed(qname[:-13].split('.')))
         record = dnslib.DNSRecord(header=dnslib.DNSHeader(id=request.header.id, qr=1,aa=1,ra=1), a=dnslib.RR(qname, rdata=dnslib.A(ipaddr)))
         return record
     if 'USERDNSDOMAIN' in os.environ:
         user_dnsdomain = '.' + os.environ['USERDNSDOMAIN'].lower()
         if qname.endswith(user_dnsdomain):
             qname = qname[:-len(user_dnsdomain)]
             if '.' not in qname:
                 if not self.dns_intranet_servers:
                     logging.warning('qname=%r is a plain hostname, need intranet dns server!!!', qname)
                     return dnslib.DNSRecord(header=dnslib.DNSHeader(id=request.header.id, rcode=3))
                 qname += user_dnsdomain
                 dnsservers = self.dns_intranet_servers
     try:
         return self.dns_cache.get((qname, qtype))
     except KeyError:
         pass
     try:
         dns_resolve = dnslib_resolve_over_tcp if qname.endswith(self.dns_tcpover) else dnslib_resolve_over_udp
         kwargs = {'blacklist': self.dns_blacklist, 'turstservers': self.dns_trust_servers}
         record = dns_resolve(request, dnsservers, self.dns_timeout, **kwargs)
         ttl = max(x.ttl for x in record.rr) if record.rr else 600
         self.dns_cache.set((qname, qtype), record, ttl * 2)
         return record
     except socket.gaierror as e:
         logging.warning('resolve %r failed: %r', qname, e)
         return dnslib.DNSRecord(header=dnslib.DNSHeader(id=request.header.id, rcode=3))
Beispiel #3
0
	async def service_client(self, reader: aio.StreamReader, writer: aio.StreamWriter) -> None:
		try:
			while True:
				# Parse DNS query packet into a request
				prefix = await reader.readexactly(2)
				query = await reader.readexactly(struct.unpack('!H', prefix)[0])
				request = dns.DNSRecord.parse(query)

				response = await self._resolver.resolve(request)

				# Pack DNS response into answer
				answer = response.pack()
				writer.write(struct.pack('!H', len(answer)) + answer)
				await writer.drain()

		# Connection likely closed or reset by client
		except aio.IncompleteReadError:
			pass

		# Failed to parse DNS query
		except dns.DNSError:
			writer.write(dns.DNSRecord(dns.DNSHeader(rcode=getattr(dns.RCODE, 'FORMERR'))).pack())
			await writer.drain()

		# Cleanly close client connection
		finally:
			if not writer.is_closing():
				writer.close()
				await writer.wait_closed()
Beispiel #4
0
    def build_answer(self, d, err, aa, answer, authority, additional):
        # Construct answer
        reply = dnslib.DNSRecord(
            dnslib.DNSHeader(qr=1, aa=aa, rd=0, rcode=err, id=d.header.id))
        reply.questions = d.questions
        # answer section
        for rr in answer:
            print rr
            reply.add_answer(
                dnslib.RR(rtype=rr['type'],
                          rclass=rr['class'],
                          ttl=rr['ttl'],
                          rname=rr['name'],
                          rdata=dnslib.RDMAP[dnslib.QTYPE[rr['type']]](
                              rr['rdata'])))
        # authority section
        for rr in authority:
            reply.add_answer(
                dnslib.RR(rtype=rr['type'],
                          rclass=rr['class'],
                          ttl=rr['ttl'],
                          rdata=rr['rdata']))
        # additional section
        for rr in additional:
            reply.add_answer(
                dnslib.RR(rtype=QRTYPE[rr['type']],
                          rclass=QRCLASS[rr['class']],
                          ttl=rr['ttl'],
                          rdata=rr['rdata']))

        return reply.pack()
Beispiel #5
0
 def _build_response(self, data):
     """
     Builds the DNS response given binary data as a query.
     :param data: binary data in the form of a DNS query.
     :return: DNS response ready to be encoded into binary form.
     """
     request = dnslib.DNSRecord.parse(data)
     recursion_desired = request.header.rd
     id = request.header.id
     answer, authority, additional, aa, rcode, ok = [], [], [], 0, 0, True
     if request.ar != []:
         ok, opt = self._edns_check(request.ar[0])
         additional.append(opt)
     if ok:
         for question in request.questions:
             domain = question.qname.idna()
             rr_set, auth_set, addi_set = search(domain, question.qtype)
             answer += rr_set
             authority += auth_set
             additional += addi_set
         if authority != [] or answer != []:
             aa = 1  # Mark as authorative answer.
         elif answer == [] and authority == []:
             rcode = 5  # Refuse unknown domains.
     # Build the response.
     return dnslib.DNSRecord(dnslib.DNSHeader(id=id,
                                              qr=1,
                                              aa=aa,
                                              ra=0,
                                              rd=recursion_desired,
                                              rcode=rcode),
                             questions=request.questions,
                             rr=answer,
                             auth=authority,
                             ar=additional)
Beispiel #6
0
def cloud_spy(nameserver=None):
    # get a local DNS server list
    if nameserver == None:
        nameservers = get_nameserver_from_registry()
        if len(nameservers) > 0:
            print '# Your DNS Server List'
            i = 0
            # print ALL DNS servers
            for nameserver in nameservers:
                i += 1
                print '[%d] ' % i, nameserver
            # User can choose a DNS server
            idx = raw_input('\nWhat do you choose? ')
            nameserver = nameservers[int(idx) - 1]
            print '\n# A DNS Server of your choice : ', nameserver

    for key, value in CLOUD_DOMAIN.items():
        # create a DNS request packet (wire format)
        wire_query = dnslib.DNSRecord(
            dnslib.DNSHeader(rd=0),  # RD(Recursion Desired) don't set up.
            q=dnslib.DNSQuestion(value))
        wire_query = wire_query.pack()

        # query to dns server
        response = query_domain(wire_query, nameserver)
        parse_rr(key, value, str(dnslib.DNSRecord.parse(response)))
Beispiel #7
0
    def run(self):
        while True:
            try:
                full_query, fromaddr = self.client_sock.recvfrom(1024)
                query = dnslib.DNSRecord.parse(full_query)

                print(str(query.header.q))
                if str(query.q.qname)+str(query.q.qtype) in self.cache:
                    from_cache_tuple = self.cache.get(str(query.q.qname)+str(query.q.qtype))

                    print("осталось жить пакету" + str(from_cache_tuple[0] - time.time()))

                    if from_cache_tuple[0] < time.time():
                        self.update_cache(full_query,fromaddr)
                    else:
                        from_cache = from_cache_tuple[1]
                        header = dnslib.DNSHeader(id=query.header.id,
                                                  q=from_cache.header.q,
                                                  )
                        new_answer = dnslib.DNSRecord(header,
                                                      query.questions,
                                                      self.make_RRs(
                                                          from_cache.rr,
                                                          from_cache_tuple[0]))
                        answer1 = new_answer.pack()
                        self.client_sock.sendto(answer1, fromaddr)
                        print("from cache")
                else:
                    self.update_cache(full_query,fromaddr)

            except socket.timeout:
                print("Что-то явно не так")
                continue
Beispiel #8
0
    def dns_response(self, data):

        request = dnslib.DNSRecord.parse(data)

        self.logger.debug("request:%s" % request)

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

        qname = request.q.qname
        qn = str(qname)
        qtype = request.q.qtype
        qt = dnslib.QTYPE[qtype]

        addrs = self.resolve(qname, qt)

        if qt in ["A", "MX", "NS", "AAAA"]:
            for item in addrs:
                reply.add_answer(
                    dnslib.RR(rname=qname,
                              rtype=self.rtypes[qt],
                              rclass=1,
                              ttl=self.TTL,
                              rdata=self.rdatatypes[qt](item)))
                self.logger.debug("DNS reply:%s:%s" % (qt, reply))
        else:
            #TODO:*1 add the other record types e.g. SOA & txt & ...
            self.logger.error("did not find type:\n%s" % request)

        return reply.pack()
Beispiel #9
0
    def _gen_response_object(self):
        """Generate the DNS response module which will be sent back to the client.

        :returns: An object taht will be sent back to the client as DNS response.
        :rtype: Noner
        """

        self.dns_response = dnslib.DNSRecord(dnslib.DNSHeader(
            id=self.dns_data.header.id, qr=1, aa=1, ra=1),
                                             q=self.dns_data.q)
Beispiel #10
0
 def handle(self):
     data = self.request[0]
     d = dnslib.DNSRecord.parse(data)
     id = d.header.id
     sock = self.request[1]
     res = dnslib.DNSRecord(dnslib.DNSHeader(qr=1, aa=1, ra=1, id=id),
                            q=dnslib.DNSQuestion(qname),
                            a=dnslib.RR(qname,
                                        rdata=dnslib.A("101.226.103.106"),
                                        ttl=3))
     sock.sendto(bytes(res.pack()), self.client_address)
Beispiel #11
0
def create_dns_response(hostname="google.com", ip=None):
    """
    Create a DNS response packet for the specified hostname. If `ip` is
    specified (as a string, e.g., '127.0.0.1'), it will be used for the
    response. Otherwise, a not found (NXDOMAIN) response is returned.
    """
    try:
        if ip is None:
            d = dnslib.DNSRecord(
                dnslib.DNSHeader(qr=1, aa=1, ra=1, rcode=3),
                q=dnslib.DNSQuestion(hostname),
            )
        else:
            d = dnslib.DNSRecord(
                dnslib.DNSHeader(qr=1, aa=1, ra=1),
                q=dnslib.DNSQuestion(hostname),
                a=dnslib.RR(hostname, rdata=dnslib.A(ip)),
            )
        return d.pack()
    except Exception as e:
        print("DNS_CREATE failed:", e)
    return None
def main():

    # Creates internet UDP socket.
    sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

    # Binds to the specified IP and port.
    sock.bind((IP, PORT))

    while True:

        # Receives data (DNS request) and address from a client. buffer size 512 as mentioned in DNS RFC.
        data, addr = sock.recvfrom(BUFFER_SIZE)

        # Informs in the console about a request received.
        print ('Received request from {0} at port {1}.'.format(addr[0], addr[1]))

        try:
            
            # Decodes data to DNS request.
            dns_req = dnslib.DNSRecord.parse(data)
        
        except:
        
            # Informs in the console that the request is corrupted.
            print("Failed decoding the request due to corruption.")
        
        else:
            
            # For each question in the clients DNS request:
            for question in dns_req.questions:

                # Gets the name queried in the question.
                q_name = question.get_qname()

                # Generates a reply to the client.
                dns_rep = dnslib.DNSRecord(dnslib.DNSHeader(id=dns_req.header.id,qr=1,aa=1,ra=1),q=dnslib.DNSQuestion(q_name),a=dnslib.RR(q_name,rdata=dnslib.A(lookup_name(q_name))))
                
                try:
                
                    # Sends the reply generated to the client.
                    sock.sendto(bytes(dns_rep.pack()), addr)
                
                except:
                
                    # Informs in the console that sending the reply failed.
                    print("Failed sending reply.")
                
                else:
                
                    # Informs in the console about a reply sent.
                    print ('Sent reply to {0} at port {1}.\n'.format(addr[0], addr[1]))
def test_on_client_request_with_cache_expired(greendns):
    qname = "qqq.com"
    id = 1024
    s = init_greendns_session(greendns, qname, dnslib.QTYPE.A, id)
    res = dnslib.DNSRecord(dnslib.DNSHeader(qr=1, aa=1, ra=1),
                           q=dnslib.DNSQuestion(qname),
                           a=dnslib.RR(qname,
                                       rdata=dnslib.A("101.226.103.106"),
                                       ttl=3))
    greendns.cache.add(("qqq.com.", 1), res, 3)
    time.sleep(4)
    is_continue, raw_resp = greendns.on_client_request(s)
    assert is_continue
    assert not raw_resp
def test_on_upstream_response_not_A(greendns):
    qname = "www.microsoft.com"
    qresult = "www.microsoft.com-c-2.edgekey.net."
    s = init_greendns_session(greendns, qname, dnslib.QTYPE.CNAME)
    res = dnslib.DNSRecord(dnslib.DNSHeader(qr=1, aa=1, ra=1),
                           q=dnslib.DNSQuestion(qname),
                           a=dnslib.RR(qname,
                                       rtype=dnslib.QTYPE.CNAME,
                                       rdata=dnslib.CNAME(qresult),
                                       ttl=3))
    s.server_resps[local_dns1] = bytes(res.pack())
    resp = greendns.on_upstream_response(s, local_dns1)
    assert resp
    d = dnslib.DNSRecord.parse(resp)
    assert str(d.rr[0].rdata) == qresult
Beispiel #15
0
def fakeReplys(qid):
    """
	This method craft a fake DNS response packet where associate the bankofallan.co.uk to the badguy ip.
	
	qid: Is the queryID to assign to the crafted packet.
	"""
    # craft fake DNS query response
    fakeReplyPacket = dnslib.DNSRecord(
        dnslib.DNSHeader(id=qid, qr=1, aa=1, ra=1),
        q=dnslib.DNSQuestion("www1337.bankofallan.co.uk"),
        a=dnslib.RR("bankofallan.co.uk",
                    dnslib.QTYPE.A,
                    rdata=dnslib.A(badguyIP),
                    ttl=10000)).pack()
    return fakeReplyPacket
def test_on_upstream_response_invalid_A(greendns):
    qname = "www.x.net"
    s = init_greendns_session(greendns, qname, dnslib.QTYPE.A)
    res = dnslib.DNSRecord(dnslib.DNSHeader(qr=1, aa=1, ra=1),
                           q=dnslib.DNSQuestion(qname),
                           a=dnslib.RR(qname, rdata=dnslib.A("1.2.4.8"),
                                       ttl=3))
    s.server_resps[local_dns1] = bytes(res.pack())
    resp = greendns.on_upstream_response(s, local_dns1)
    d = dnslib.DNSRecord.parse(resp)
    assert str(d.rr[0].rdata) == "1.2.4.8"

    s.server_resps[local_dns1] = b'123456'
    resp = greendns.on_upstream_response(s, local_dns1)
    assert not resp
def test_on_upstream_response_BD(greendns):
    qname = "google.com"
    s = init_greendns_session(greendns, qname, dnslib.QTYPE.A)
    res = dnslib.DNSRecord(dnslib.DNSHeader(qr=1, aa=1, ra=1),
                           q=dnslib.DNSQuestion(qname),
                           a=dnslib.RR(qname, rdata=dnslib.A("1.2.3.4"),
                                       ttl=3))
    s.server_resps[local_dns1] = bytes(res.pack())
    resp = greendns.on_upstream_response(s, local_dns1)
    assert not resp

    res.rr[0].rdata = dnslib.A("172.217.24.14")
    s.server_resps[foreign_dns] = bytes(res.pack())
    resp = greendns.on_upstream_response(s, foreign_dns)
    assert resp
    d = dnslib.DNSRecord.parse(resp)
    assert str(d.rr[0].rdata) == "172.217.24.14"
def test_on_upstream_response_AC(greendns):
    qname = "www.coding.net"
    s = init_greendns_session(greendns, qname, dnslib.QTYPE.A)
    res = dnslib.DNSRecord(dnslib.DNSHeader(qr=1, aa=1, ra=1),
                           q=dnslib.DNSQuestion(qname),
                           a=dnslib.RR(qname,
                                       rdata=dnslib.A("120.132.59.101"),
                                       ttl=3))
    s.server_resps[foreign_dns] = bytes(res.pack())
    resp = greendns.on_upstream_response(s, foreign_dns)
    assert not resp

    res.rr[0].rdata = dnslib.A("219.146.244.91")
    s.server_resps[local_dns1] = bytes(res.pack())
    resp = greendns.on_upstream_response(s, local_dns1)
    assert resp
    d = dnslib.DNSRecord.parse(resp)
    assert str(d.rr[0].rdata) == "219.146.244.91"
def test_on_upstream_response_AD(greendns):
    qname = "www.microsoft.com"
    s = init_greendns_session(greendns, qname, dnslib.QTYPE.A)
    res = dnslib.DNSRecord(dnslib.DNSHeader(qr=1, aa=1, ra=1),
                           q=dnslib.DNSQuestion(qname),
                           a=dnslib.RR(qname,
                                       rdata=dnslib.A("184.85.123.14"),
                                       ttl=3))
    s.server_resps[foreign_dns] = bytes(res.pack())
    resp = greendns.on_upstream_response(s, foreign_dns)
    assert not resp

    res.rr[0].rdata = dnslib.A("183.136.212.50")
    s.server_resps[local_dns1] = bytes(res.pack())
    resp = greendns.on_upstream_response(s, local_dns1)
    assert resp
    d = dnslib.DNSRecord.parse(resp)
    assert str(d.rr[0].rdata) == "183.136.212.50"
Beispiel #20
0
def answer(dnsq, addr):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    answer = dnsq.reply()
    answer.header = dnslib.DNSHeader(id=dnsq.header.id,
                                     aa=1,
                                     qr=1,
                                     ra=1,
                                     rcode=3)
    answer.add_auth(
        dnslib.RR("testing.arkc.org",
                  dnslib.QTYPE.SOA,
                  ttl=3600,
                  rdata=dnslib.SOA("freedom.arkc.org",
                                   "webmaster." + "freedom.arkc.org",
                                   (20150101, 3600, 3600, 3600, 3600))))
    answer.set_header_qa()
    packet = answer.pack()
    s.sendto(packet, addr)
Beispiel #21
0
	async def _process_query(self, client: tuple, query: bytes) -> None:
		try:
			# Parse DNS query packet into a request
			request = dns.DNSRecord.parse(query)
			response = await self._resolver.resolve(request)

			# Pack DNS response into answer packet and truncate if necessary
			answer = response.pack()
			if len(answer) > DotUdpServer.max_udp_size:
				answer = response.truncate().pack()

		# Failed to parse DNS query
		except dns.DNSError:
			answer = dns.DNSRecord(dns.DNSHeader(rcode=getattr(dns.RCODE, 'FORMERR'))).pack()

		# Reply to client with DNS answer
		finally:
			self._transport.sendto(answer, client)
Beispiel #22
0
 def response(self):
     if self.lookup().is_valid():
         record = dnslib.DNSRecord(dnslib.DNSHeader(
             id=self._record.header.id, qr=1, rd=1, ra=1),
                                   q=dnslib.DNSQuestion(self.domain))
         for address in self.multiaddr:
             answer = dnslib.RR(address.domain,
                                ttl=address.time,
                                rtype=qtype[address.rtype],
                                rclass=_class[address.rclass],
                                rdata=getattr(dnslib,
                                              address.rtype)(address.ip))
             record.add_answer(answer)
         packs = record.pack()
     else:
         try:
             packs = self.dnsLookup.record.pack()
         except DNSLookupException:
             return b''
     return packs
def test_shuffer_A(greendns):
    qname = "qq.com"
    id = 1024
    s = init_greendns_session(greendns, qname, dnslib.QTYPE.A, id)
    res = dnslib.DNSRecord(dnslib.DNSHeader(qr=1, aa=1, ra=1),
                           q=dnslib.DNSQuestion(qname),
                           a=dnslib.RR(qname,
                                       dnslib.QTYPE.CNAME,
                                       rdata=dnslib.CNAME("https.qq.com"),
                                       ttl=3))
    res.add_answer(dnslib.RR(qname, rdata=dnslib.A("101.226.103.106"), ttl=3))
    res.add_answer(dnslib.RR(qname, rdata=dnslib.A("101.226.103.107"), ttl=3))
    greendns.cache.add(("qq.com.", 1), res, 3)
    d = None
    for i in range(10):
        is_continue, raw_resp = greendns.on_client_request(s)
        assert not is_continue
        assert raw_resp
        d = dnslib.DNSRecord.parse(raw_resp)
        if str(d.rr[1].rdata) == "101.226.103.107":
            break
    assert d.rr[0].rtype == dnslib.QTYPE.CNAME
    assert str(d.rr[1].rdata) == "101.226.103.107"
Beispiel #24
0
 def try_get_from_cache(self, query):
     parsed_query = dnslib.DNSRecord.parse(query)
     # print(self.cache[0][1].rtype)
     # print(parsed_query.q.qtype)
     entries = [
         entry for entry in self.cache
         if entry[0] == str(parsed_query.q.qname) and entry[1].rtype ==
         parsed_query.q.qtype and entry[2] > time.time()
     ]
     print(entries)
     if not entries:
         return
     answer = dnslib.DNSRecord(q=parsed_query.q,
                               header=dnslib.DNSHeader(
                                   qr=1, id=parsed_query.header.id))
     for entry in entries:
         answer.add_answer(
             dnslib.RR(rname=entry[1].rname,
                       rtype=entry[1].rtype,
                       rclass=entry[1].rclass,
                       rdata=entry[1].rdata,
                       ttl=int(entry[2] - time.time())))
     print(repr(answer))
     return bytes(answer.pack())
Beispiel #25
0
    def answer(self, dnsq, addr):
        q_contents = str(dnsq.q.get_qname())

        if self.delegatedomain in q_contents:
            delegatedomain = self.delegatedomain
            selfdomain = self.selfdomain
        else:
            try:
                q_contents_split = q_contents.split('.')
                delegatedomain = '.'.join(q_contents_split[-5:])
                selfdomain = '.'.join([q_contents_split[-5]] +
                                      q_contents_split[-3:])
            except Exception:
                delegatedomain = self.delegatedomain
                selfdomain = self.selfdomain
        if dnsq.q.qtype == dnslib.QTYPE.MX:
            answer = dnsq.reply(ra=1, aa=1)
            answer.add_answer(*dnslib.RR.fromZone(q_contents + " 3600 MX 10 " +
                                                  selfdomain))
        else:
            answer = dnsq.reply()
            answer.header = dnslib.DNSHeader(id=dnsq.header.id,
                                             aa=1,
                                             qr=1,
                                             ra=1,
                                             rcode=3)
            answer.add_auth(
                dnslib.RR(
                    delegatedomain,
                    dnslib.QTYPE.SOA,
                    ttl=3600,
                    rdata=dnslib.SOA(selfdomain, "webmaster." + selfdomain,
                                     (20130101, 3600, 3600, 3600, 3600))))
        answer.set_header_qa()
        packet = answer.pack()
        self.transport.write(packet, addr)
Beispiel #26
0
    def handle(self):

        request = dnslib.DNSRecord.parse(self.request[0])
        """ see http://www.networksorcery.com/enp/protocol/dns.htm 
        QR flag is 1 (0 = Query, 1 = Response)
        AA flag is 1 (0 = Not authoritative, 1 = Is authoritative)
        
        """
        reply = dnslib.DNSRecord(dnslib.DNSHeader(id=request.header.id, qr=1, aa=1),
                                 q=request.q)

        reply.add_answer(dnslib.RR(
            rname=request.q.qname,
            rtype=1,
            rdata=dnslib.A(self.DNS_LOOKUP),

        ))

        request_name = str(request.q.qname)
        if request_name in self.TXT_LOOKUP:
            for answer in self.TXT_LOOKUP[request_name]:
                reply.add_answer(dnslib.RR(
                    request.q.qname,
                    ttl=300,
                    rtype=dnslib.QTYPE.TXT,
                    rdata=dnslib.TXT(answer.encode("utf-8"))
                ))
                print('dnsserver served txt record for {}: {}'.format(request_name, answer))
        else:
            print('dnsserver didn\'t find txt record for {}'.format(request_name))
            # print("{} not in memory".format(request_name))
            # print("memory", self.TXT_LOOKUP)
            # print(type(request_name))
            pass

        self.send_data(reply.pack())
Beispiel #27
0
    def start(self):
        self.sDNS.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sDNS.bind((self.interface, self.port))
        print("[*] Started DNS server on port {}".format(self.port))

        while self.running:
            data, addr = self.sDNS.recvfrom(512)
            parsedDNS = dnslib.DNSRecord.parse(data)

            # We send fake IP to adAS
            if (addr[0] in self.blacklist):
                ip = self.ipToSpoof
            else:
                ip = self.realIP

            print("[DNS] Response: {} -> {}".format(
                parsedDNS.questions[0].qname, ip))
            response = dnslib.DNSRecord(
                dnslib.DNSHeader(qr=1, aa=1, ra=1, id=parsedDNS.header.id),
                q=dnslib.DNSQuestion(parsedDNS.questions[0].qname),
                a=dnslib.RR(parsedDNS.questions[0].qname, rdata=dnslib.A(ip)))
            self.sDNS.sendto(response.pack(), addr)

        self.sDNS.close()
Beispiel #28
0
    except:
        return {}


cache = load_cache()
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 53))
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

while True:
    request, address = server.recvfrom(2048)
    x = dnslib.DNSRecord.parse(request)
    if cache.get((x.questions[0].qname, x.questions[0].qtype)):
        print('cache!')
        header = dnslib.DNSHeader(
            x.header.id,
            q=1,
            a=len(cache.get((x.questions[0].qname, x.questions[0].qtype))[0]))
        response = dnslib.DNSRecord(
            header, x.questions,
            cache.get((x.questions[0].qname, x.questions[0].qtype))[0])
        print("Ответ отправлен из кэша\n")
        server.sendto(response.pack(), address)
    else:
        try:
            client.sendto(request, (forwarder, 53))
            response_from_dns, _ = client.recvfrom(2048)
            y = dnslib.DNSRecord.parse(response_from_dns)
            print("Получен ответ ", y)
            print("\n")
            cache[(y.questions[0].qname,
                   y.questions[0].qtype)] = y.rr, time.time()
Beispiel #29
0
 def handle(self, data, address):
     logging.debug('receive from %r data=%r', address, data)
     request = dnslib.DNSRecord.parse(data)
     qname = str(request.q.qname)
     qtype = request.q.qtype
     try:
         reply_data = self.dns_cache.get((qname, qtype))
     except KeyError:
         reply_data = ''
     sock_v4 = sock_v6 = None
     socks = []
     is_local_hostname = '.' not in qname
     if 'USERDNSDOMAIN' in os.environ:
         is_local_hostname = qname.lower().endswith(
             '.' + os.environ['USERDNSDOMAIN'].lower())
     if is_local_hostname and not self.dns_intranet_servers:
         logging.warning(
             'qname=%r is a plain hostname, need intranet dns server!!!',
             qname)
         reply = dnslib.DNSRecord(
             header=dnslib.DNSHeader(id=request.header.id, rcode=3))
         self.sendto(reply.pack(), address)
         return
     dns_v4_servers = self.dns_v4_servers if not is_local_hostname else [
         x for x in self.dns_intranet_servers if ':' not in x
     ]
     dns_v6_servers = self.dns_v6_servers if not is_local_hostname else [
         x for x in self.dns_intranet_servers if ':' in x
     ]
     if dns_v4_servers:
         sock_v4 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
         socks.append(sock_v4)
     if dns_v6_servers:
         sock_v6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
         socks.append(sock_v6)
     for _ in xrange(2):
         if reply_data:
             break
         try:
             need_reply_servers = set()
             for dnsserver in dns_v4_servers:
                 sock_v4.sendto(data, (dnsserver, 53))
                 need_reply_servers.add(dnsserver)
             for dnsserver in dns_v6_servers:
                 sock_v6.sendto(data, (dnsserver, 53))
                 need_reply_servers.add(dnsserver)
             timeout_at = time.time() + self.dns_timeout
             while time.time() < timeout_at:
                 if reply_data:
                     break
                 ins, _, _ = select.select(socks, [], [], 0.1)
                 for sock in ins:
                     reply_data, (reply_server, _) = sock.recvfrom(512)
                     reply = dnslib.DNSRecord.parse(reply_data)
                     iplist = [str(x.rdata) for x in reply.rr]
                     if any(x in self.dns_blacklist for x in iplist):
                         logging.warning(
                             'query qname=%r reply bad iplist=%r, continue',
                             qname, iplist)
                         reply_data = ''
                         continue
                     if reply.header.rcode and not iplist and need_reply_servers and reply_server not in self.dns_trust_servers:
                         try:
                             need_reply_servers.remove(reply_server)
                         except KeyError:
                             pass
                         if need_reply_servers:
                             logging.warning(
                                 'query qname=%r qtype=%r reply nonzero rcode=%r, wait other need_reply_servers=%s, continue',
                                 qname, qtype, reply.header.rcode,
                                 need_reply_servers)
                             reply_data = ''
                             continue
                         else:
                             logging.info(
                                 'query qname=%r qtype=%r reply nonzero rcode=%r',
                                 qname, qtype, reply.header.rcode)
                     ttl = max(x.ttl for x in reply.rr) if reply.rr else 600
                     logging.debug(
                         'query qname=%r qtype=%r reply_server=%r reply iplist=%s, ttl=%r',
                         qname, qtype, reply_server, iplist, ttl)
                     if iplist or qname.endswith('.in-addr.arpa'):
                         self.dns_cache.set((qname, qtype), reply_data,
                                            ttl * 2)
                     break
         except socket.error as e:
             logging.warning('handle dns data=%r socket: %r', data, e)
     for sock in socks:
         sock.close()
     if reply_data:
         return self.sendto(data[:2] + reply_data[2:], address)
Beispiel #30
0
    def processRequest(self, request):

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

        qname = request.q.qname
        qn = str(qname)
        qtype = request.q.qtype
        qt = dnslib.QTYPE[qtype]
        if qn == self.D or qn.endswith('.' + self.D):

            for name, rrs in self.records.items():
                if name == qn:
                    for rdata in rrs:
                        rqt = rdata.__class__.__name__
                        if qt in ['*', rqt]:
                            reply.add_answer(
                                dnslib.RR(rname=qname,
                                          rtype=getattr(dnslib.QTYPE, rqt),
                                          rclass=1,
                                          ttl=self.TTL,
                                          rdata=rdata))

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

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

        for question in request.questions:

            if (question.qtype == dnslib.QTYPE.TXT):
                #only process TXT record requests
                content = str(question.qname)[:-1]
                if content.endswith(self.D[:-1]):
                    content = content[:-len(self.D[:-1]) - 1]

                key = content[:4]

                if key in self.fIP:
                    content = str(content[4:])
                    self.fIP[key][3] += content
                    self.fIP[key][1] -= len(content)
                    #print(key, content,len(content),self.fIP[key][1] )

                    #print("Left: "+str(self.fIP[sIP][1]))
                    self.progressBar(
                        self.fIP[key][1], self.fIP[key][4], "Receiving '" +
                        self.fIP[key][0] + "' with index " + key)
                    reply.add_answer(
                        dnslib.RR(rname=qname,
                                  rtype=question.qtype,
                                  rclass=1,
                                  ttl=self.TTL,
                                  rdata=dnslib.TXT(content)))
                    #reply.add_answer(dnslib.RR(rname=qname, rtype=question.qtype, rclass=1, ttl=self.TTL, rdata=dnslib.TXT("OK")))
                    if (self.fIP[key][1] == 0):
                        #we have received the entire file. Time to write it.
                        content_decoded = base64.standard_b64decode(
                            self.fIP[key][3])
                        with open(self.fIP[key][0], 'wb') as newfile:
                            newfile.write(content_decoded)

                        hashedWord = md5(content_decoded).hexdigest()
                        if (self.fIP[key][2] == hashedWord):
                            print("\nFile successfully received")
                            reply.add_answer(
                                dnslib.RR(rname=qname,
                                          rtype=question.qtype,
                                          rclass=1,
                                          ttl=self.TTL,
                                          rdata=dnslib.TXT("OK")))

                        else:
                            print("\nFile received but failed hash:")
                            reply.add_answer(
                                dnslib.RR(rname=qname,
                                          rtype=question.qtype,
                                          rclass=1,
                                          ttl=self.TTL,
                                          rdata=dnslib.TXT("FAIL HASH")))

                        del self.fIP[key]

                else:
                    # new connection. we expect a file name
                    print("New file:", content)
                    parts = content.split("|")
                    if (len(parts) == 3):
                        #we have valid request
                        print("new file upload: ", content)
                        self.fIP[parts[2][:4]] = [
                            os.path.basename(parts[0]),
                            int(parts[1]), parts[2], "",
                            int(parts[1])
                        ]
                    reply.add_answer(
                        dnslib.RR(rname=qname,
                                  rtype=question.qtype,
                                  rclass=1,
                                  ttl=self.TTL,
                                  rdata=dnslib.TXT("OK")))

            else:
                reply.add_answer(
                    dnslib.RR(rname=qname,
                              rtype=question.qtype,
                              rclass=1,
                              ttl=self.TTL,
                              rdata=dnslib.A(self.IP)))

            #print("responding:",reply)
            return reply.pack()