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()
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))
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()
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()
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)
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)))
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
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()
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)
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)
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
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"
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)
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)
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"
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())
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)
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())
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()
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()
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)
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()