def _add_additional(addi_list): """ Given a domain and an additional set, this function will add the A records for the UH DNS nameservers to the set. :param addi_list: Additional set to add to. """ if addi_list == []: addi_list.append( dnslib.RR(rname="ns1.uh-dns.com.", rtype=dnslib.QTYPE.A, rdata=dnslib.A("18.130.161.247"), ttl=3600)) addi_list.append( dnslib.RR(rname="ns1.uh-dns.com.", rtype=dnslib.QTYPE.AAAA, rdata=dnslib.AAAA("2a05:d01c:35b:7601::4"), ttl=3600)) addi_list.append( dnslib.RR(rname="ns2.uh-dns.com.", rtype=dnslib.QTYPE.A, rdata=dnslib.A("18.130.86.161"), ttl=3600)) addi_list.append( dnslib.RR(rname="ns2.uh-dns.com.", rtype=dnslib.QTYPE.AAAA, rdata=dnslib.AAAA("2a05:d01c:35b:7600::4"), ttl=3600))
def domain2ip(self, qdomain, ips): ans = [] if type(ips) == list: for ip in ips: ans.append({ qdomain: dnslib.RR(qdomain, rdata=dnslib.A(ip), ttl=self.ttl) }) elif type(ips) == str: ans.append({ qdomain: dnslib.RR(qdomain, rdata=dnslib.A(ips), ttl=self.ttl) }) return ans
def handle(self): try: data = self.get_data() query = dnslib.DNSRecord.parse(data) reply = query.reply() answers = [] if reply.get_q().qtype == dnslib.QTYPE.TXT: try: challenge_files = os.listdir(BaseDNSRequestHandler.challenges_path) for challenge_file in challenge_files: if challenge_file.startswith(str(reply.get_q().qname).strip('.')): with open(os.path.join(BaseDNSRequestHandler.challenges_path, challenge_file), 'r') as challenge_data: answers.append(dnslib.RR(rname=reply.get_q().qname, rtype=reply.get_q().qtype, ttl=60, rdata=dnslib.TXT(challenge_data.read().strip()))) except OSError: pass else: answers.append(dnslib.RR(rname=reply.get_q().qname, ttl=60, rdata=dnslib.A(LISTEN_ADDRESS))) for answer in answers: reply.add_answer(answer) self.send_data(reply.pack()) except Exception as e: print(e)
async def _get_record(self, request, client_writer): domain = str(request.questions[0].qname)[:-1] qtype = request.questions[0].qtype logger.info('dns_request: %s, %s', domain, qtype) if not self.conf.GET_PROXY.isgfwed_resolver(domain): # try resolve with getaddrinfo first logger.debug('not gfwed.') if qtype in (dnslib.QTYPE.A, dnslib.QTYPE.AAAA, dnslib.QTYPE.ANY): result_list = await resolve(domain, 0) response = request.reply() for result in result_list: if result[0] == socket.AF_INET and qtype in ( dnslib.QTYPE.A, dnslib.QTYPE.ANY): response.add_answer( dnslib.RR(domain, dnslib.QTYPE.A, rdata=dnslib.A(result[1]))) elif result[0] == socket.AF_INET6 and qtype in ( dnslib.QTYPE.AAAA, dnslib.QTYPE.ANY): response.add_answer( dnslib.RR(domain, dnslib.QTYPE.AAAA, rdata=dnslib.AAAA(result[1]))) return response await self.tcp_dns_record(request, client_writer)
def pack_dns(dns, answers, soa=None): def content_type(x): # valid ip if socket.inet_aton(x): return 'A' else: return 'CNAME' if answers: for ans in answers: # logger.info('ans ' + ans) if content_type(ans[1]) == 'A': dns.add_answer( dnslib.RR(ans[0], dnslib.QTYPE.A, rdata=dnslib.A(ans[1]))) elif content_type(ans[1]) == 'CNAME': dns.add_answer( dnslib.RR(ans[0], dnslib.QTYPE.CNAME, rdata=dnslib.CNAME(ans[1]))) elif soa: soa_content = soa[1].split() dns.add_auth( dnslib.RR(soa[0], dnslib.QTYPE.SOA, rdata=dnslib.SOA(soa_content[0], soa_content[1], (int(i) for i in soa_content[2:])))) return dns
def SendDnsData(data, s, addr): global Remote_dns_server global Remote_dns_port '''dns请求报文''' request_packet = dnslib.DNSRecord.parse(data) '''dns请求报文的域名''' domain = request_packet.get_q().get_qname() '''dns响应报文''' response_packet = request_packet.reply() ip = Search_key_ip(str(domain)) if ip != None: print(domain, ':', ip) response_packet.add_answer( dnslib.RR(domain, dnslib.QTYPE.A, rdata=dnslib.A(ip), ttl=60)) s.sendto(response_packet.pack(), addr) else: data = AddEDNSOption(data, addr[0]) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.settimeout(5) sock.sendto(data, (Remote_dns_server, Remote_dns_port)) while True: try: rspdata = sock.recv(4096) except Exception as e: logging.warn("Recv:\t%s" % e) break s.sendto(rspdata, addr) break
def run(self): fd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) fd.bind(('', 53)) while True: try: packet, isp_dns_address = fd.recvfrom(8192) req = dnslib.DNSRecord.parse(packet) a = req.reply() q_name = req.get_q().qname q_type = req.get_q().qtype q_type_str = dnslib.QTYPE.get(q_type) if q_type_str == 'A': a.add_answer( dnslib.RR(q_name, dnslib.QTYPE.A, rdata=dnslib.A(SERVER_PUBLIC_IP), ttl=600)) lock.acquire() k = str(q_name) domain_dns_dict[k] = isp_dns_address[0] delete_later(domain_dns_dict, k) lock.release() print('dns request : ', q_name, q_type_str, isp_dns_address) sys.stdout.flush() fd.sendto(a.pack(), isp_dns_address) except Exception as e: print(e) sys.stdout.flush()
def _alias_search(q_type, record, rr_list, auth_list, addi_list): """ If no A or AAAA records exist this function will add any fixed alias records. :param q_type: Query type (A or AAAA) alias records accepted. :param record: Record from DB. :param rr_list: resource record list. :param auth_list: authority list. :param addi_list: additional list. """ try: alias_record = record["ALIAS"] ttl = int(alias_record["ttl"]) question = dnslib.DNSRecord.question(alias_record["domain"], qtype=dnslib.QTYPE[q_type]) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.settimeout(1) sock.bind(("", 0)) # Bind to any available IP and port. sock.sendto(question.pack(), ("10.0.0.2", 53)) res = dnslib.DNSRecord.parse(sock.recv(4096)) sock.close() for r in res.rr: ip = str(r.rdata) if q_type == dnslib.QTYPE.A: rdata = dnslib.A(ip) elif q_type == dnslib.QTYPE.AAAA: rdata = dnslib.AAAA(ip) rr_list.append(dnslib.RR(rname=record["domain"], rtype=q_type, rdata=rdata, ttl=ttl)) _add_authority(record["domain"], auth_list) _add_additional(addi_list) except: pass
def cloak(self, request, handler): domain = GetDomainNameFromRequest(request) for rule in self.cloakrules: if rule.search(domain): reply = request.reply() # Return an A record if target is IPV4 address if rule.targetIsIp4(): reply.add_answer( RR(request.questions[0].qname, rtype=QTYPE.A, rdata=dnslib.A(rule.target), ttl=self.DEFAULT_TTL)) return reply # Add a CNAME if the target domain is different if domain != rule.target: reply.add_answer( RR(request.questions[0].qname, rtype=QTYPE.CNAME, rdata=dnslib.CNAME(rule.target), ttl=self.DEFAULT_TTL)) subquery = DNSRecord.question(rule.target) subresp = self.upstream_resolve(subquery, handler) for record in subresp.rr: reply.add_answer(record) return reply
def test_on_upstream_response_BC(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("8.8.8.8"), 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("1.2.4.8") 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) == "1.2.4.8"
def handle(self): global count count=count+1 #序号 request_data = self.request[0] client_socket = self.request[1] #内部搜索 d=DNSRecord.parse(request_data) qname=str(d.q.qname) qid=d.header.id search=cache.get(qname) #print(qname) if search: ret=d.reply() # 不良网站 if search=="0.0.0.0": ret.add_answer(dnslib.RR(qname,QTYPE.TXT,rdata=dnslib.TXT(warning))) else: ret.add_answer(dnslib.RR(qname,rdata=dnslib.A(search))) ret.header.id=qid if debug_print: print(time.asctime( time.localtime(time.time()))," ", count," ",self.client_address,qname) elif debug_print2: print("\n\n\n") print("*******Request Data***********") print(d) print("********Client Address********") print(self.client_address) print("********Search Name***********") print(qname) print("********Search IP*************") print(search) client_socket.sendto(bytes(ret.pack()), self.client_address) else: # 将请求转发到 外部 DNS redirect_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) redirect_socket.sendto(request_data, (DNS_server, 53)) response_data, address = redirect_socket.recvfrom(8192) if debug_print: print(time.asctime( time.localtime(time.time()))," ", count," ",self.client_address,qname) elif debug_print2: print("\n\n\n") print("*******Request Data***********") print(d) print("********Client Address********") print(self.client_address) print("********Search Name***********") print(qname) print("********Search IP*************") print(DNSRecord.parse(response_data)) # 将外部响应响应给客户 client_socket.sendto(response_data, self.client_address)
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 resolve(self, request, handler): reply = request.reply() qname = request.q.qname # Refuse queries thaat are not for our domain if tuple(map(str.lower, map(qname._decode, qname.label[-2:]))) != \ tuple(map(str.lower, map(self.domain._decode, self.domain.label[-2:]))): reply.header.rcode = dnslib.RCODE.REFUSED return reply # Answer questions about the root domain name # TODO(supersat): We don't need to implement this, right? if len(qname.label) <= 3: if request.q.qtype == dnslib.QTYPE.A: reply.add_answer( dnslib.RR(qname, dnslib.QTYPE.A, ttl=300, rdata=self.server_ip)) return reply subdomain = qname._decode(qname.label[1]).lower() hostname = qname._decode(qname.label[0]).lower() if BASE36_SHA256_HASH.match(subdomain) and len(qname.label) == 4: if hostname == '_acme-challenge' and \ (request.q.qtype == dnslib.QTYPE.TXT or \ request.q.qtype == dnslib.QTYPE.ANY): txt = self.redis.get('acme-dns-01-chal:{}'.format(subdomain)) if txt: reply.add_answer( dnslib.RR(qname, dnslib.QTYPE.TXT, ttl=300, rdata=dnslib.TXT(txt))) else: reply.header.rcode = dnslib.RCODE.NXDOMAIN elif IPV4_REGEX.match(hostname) and \ (request.q.qtype == dnslib.QTYPE.A or \ request.q.qtype == dnslib.QTYPE.ANY): try: ip = tuple(map(int, hostname.split('-'))) reply.add_answer( dnslib.RR(qname, dnslib.QTYPE.A, ttl=300, rdata=dnslib.A(ip))) except: reply.header.rcode = dnslib.RCODE.NXDOMAIN else: reply.header.rcode = dnslib.RCODE.NXDOMAIN return reply reply.header.rcode = dnslib.RCODE.NXDOMAIN return reply
def pack_dns(self, dns, answers, soa=None): content_type = lambda x: 'A' if re.match('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', x) else 'CNAME' if answers: for ans in answers: if content_type(ans[1]) == 'A': dns.add_answer(dnslib.RR(ans[0], dnslib.QTYPE.A, rdata=dnslib.A(ans[1]))) elif content_type(ans[1]) == 'CNAME': dns.add_answer(dnslib.RR(ans[0], dnslib.QTYPE.CNAME, rdata=dnslib.CNAME(ans[1]))) elif soa: soa_content = soa[1].split() dns.add_auth(dnslib.RR(soa[0], dnslib.QTYPE.SOA, rdata=dnslib.SOA(soa_content[0], soa_content[1], (int(i) for i in soa_content[2:])))) return dns
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_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 resolve(self, request, handler): reply = request.reply() qtype = dnslib.QTYPE[request.q.qtype] rhost = str(request.q.qname) if qtype != "A" or rhost == "etherclient.ml." or rhost == 'ns2.etherclient.ml.' or rhost == 'ns1.etherclient.ml.' or rhost.count( ".") < 3: reply.add_answer( dnslib.RR("etherclient.ml", rdata=dnslib.A("209.250.251.88"), ttl=1)) else: sub = rhost.split(".")[0] print "Sub --> " + sub if sub.startswith('next'): mainsub = rhost.split(".")[1] self.domainReqs[mainsub] = True reply.add_answer( dnslib.RR("%s.%s.etherclient.ml" % (sub, mainsub), rdata=dnslib.A("209.250.251.88"), ttl=1)) else: if sub not in self.domainReqs or self.domainReqs[sub] == False: reply.add_answer( dnslib.RR(sub + ".etherclient.ml", rdata=dnslib.A("209.250.251.88"), ttl=1)) else: print "REBINDING LOL" reply.add_answer( dnslib.RR(sub + ".etherclient.ml", rdata=dnslib.A("127.0.0.1"), ttl=1)) self.domainReqs[sub] = False return reply
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 gen_response(qt, qn): global serving_domains prefix_ = list( filter(lambda d: qn == d or qn.endswith('.' + d), serving_domains)) if len(prefix_) != 1: # print("Error: invalid request domain {} in {}".format(qn, serving_domains)) return None prefix = prefix_[0] print('REQ: ', qt, qn) if qt == 'SOA': generated_soa = dnslib.SOA( mname="todo." + domain_text, rname="*****@*****.**", times=( 201307231, # serial number 10000, # refresh 2400, # retry 604800, # expire 3600, # minimum )) return RR(rname=prefix, rtype=QTYPE.SOA, rclass=1, ttl=86400, rdata=generated_soa) # return {"mname": "todo."+domain_text, "rname": "*****@*****.**", "serial": "10", "refresh": 3600, "retry": 600, "expire": 604800, "minimum": 86400} elif qt == 'A': requested_ip = qn[:len(qn) - len(prefix)].strip('.') if not re.match(r'^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$', requested_ip): print("Invalid requested_ip: " + requested_ip) return None generated_a = dnslib.A(requested_ip) return RR(rname=qn, rtype=QTYPE.A, rclass=1, ttl=86400, rdata=generated_a) elif qt == 'NS': generated_ns = dnslib.NS(ns_ipaddr) return RR(rname=prefix, rtype=QTYPE.NS, rclass=1, ttl=86400, rdata=generated_ns) else: print("Invalid qt=" + qt) return None
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))
def ip_encode(data, ipv6) -> list: """ Encodes data to AAAA or A rdata types. """ chunk_size = IPV6_LENGTH if ipv6 else IPV4_LENGTH data = pad_bytes(data, chunk_size) if (len(data) > chunk_size): data = chunk(data, chunk_size) else: data = [data] if (ipv6): qdata = [dns.AAAA(socket.inet_ntop(socket.AF_INET6, i)) for i in data] else: qdata = [dns.A(socket.inet_ntop(socket.AF_INET, i)) for i in data] return qdata
def set_questions(self, d, qs, res): reverse = {} ans = {} for i in range(0, len(d.questions)): qstr = str(d.questions[i].get_qname()) # Check if overriden with new hostname if qstr[:-1] in qs: d.questions[i].set_qname(qs.get(qstr[:-1]) + ".") reverse[qs.get(qstr[:-1])] = qstr[:-1] # Check if we should resolve it to IP elif qstr[:-1] in res: ans[qstr[:-1]] = dnslib.RR( qstr[:-1], rdata=dnslib.A(res[qstr[:-1]]) ) return (d, reverse, ans)
def _a_search(record, rr_list, auth_list, addi_list): """ Searches and adds any A records for the domain. :param record: Overall record for domain :param rr_list: Current record list for the domain :param auth_list: Authority list for the domain :param addi_list: Additional list for the domain """ try: _alias_search(dnslib.QTYPE.A, record, rr_list, auth_list, addi_list) a_record = record["A"] ttl = int(a_record["ttl"]) for ip in a_record["value"]: rr_list.append(dnslib.RR(rname = record["domain"], rtype = dnslib.QTYPE.A, rdata = dnslib.A(ip), ttl = ttl)) _add_authority(record["domain"], auth_list) _add_additional(addi_list) except: pass
def add_answer_to_query(required_data, query): qtype = query.q.qtype q = query.q # Для каждого типа запроса добавляем интересующий ответ if qtype == dnslib.QTYPE.A: # Добавляем все A адреса for addr in required_data.addresses: query.add_answer( dnslib.RR(rname=q.qname, rclass=q.qclass, rtype=q.qtype, ttl=required_data.remain_ttl(), rdata=dnslib.A(addr))) if qtype == dnslib.QTYPE.AAAA: # Добавляем все AAAA адреса for addr in required_data.addresses: query.add_answer( dnslib.RR(rname=q.qname, rclass=q.qclass, rtype=q.qtype, ttl=required_data.remain_ttl(), rdata=dnslib.AAAA(addr))) if qtype == dnslib.QTYPE.NS: # Добавляем все NS серверы for addr in required_data.servers: query.add_answer( dnslib.RR(rname=q.qname, rclass=q.qclass, rtype=q.qtype, ttl=required_data.remain_ttl(), rdata=dnslib.NS(addr))) if qtype == dnslib.QTYPE.PTR: # Добавляем PTR query.add_answer( dnslib.RR(rname=q.qname, rclass=q.qclass, rtype=q.qtype, ttl=required_data.remain_ttl(), rdata=dnslib.PTR(required_data.name)))
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 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()
def resolve(self, request, handler): question = request.get_q() req_name = str(question.get_qname()) # TXT = 16 reply = request.reply() suffix = "._tox.{0}".format(self.ireg) if question.qtype != 16 and not req_name.endswith(self.ireg): reply.header.rcode = dnslib.RCODE.NXDOMAIN return reply if question.qtype == 16: if req_name == suffix[1:]: reply.add_answer(dnslib.RR(req_name, 16, ttl=0, rdata=dnslib.TXT(self.cryptocore.public_key.encode("ascii")))) return reply if not req_name.endswith(suffix): reply.header.rcode = dnslib.RCODE.NXDOMAIN return reply user_name = req_name[:req_name.rfind(suffix)] if len(user_name) > NAME_LIMIT_HARD and user_name[0] == "_": encrypted = user_name.replace(".", "")[1:] try: b = notsecure32_decode(encrypted) nonce = b[:4] + (b"\0" * 20) ck = b[4:36] payload = b[36:] name = self.cryptocore.dsrep_decode_name(ck, nonce, payload) except Exception: print("error >_<") reply.header.rcode = dnslib.RCODE.NXDOMAIN return reply rec = self.store.get(name.decode("utf8")) if not rec: reply.header.rcode = dnslib.RCODE.NXDOMAIN return reply base = b"v=tox3;id=" if rec.pin: r_payload = "{0}{1}{2}".format(rec.public_key, rec.pin, rec.checksum) else: r_payload = "{0}00000000{1}".format(rec.public_key, rec.checksum) msg = binascii.unhexlify(r_payload) nonce_reply = b[:4] + b"\x01" + (b"\0" * 19) ct = self.cryptocore.dsrec_encrypt_key(ck, nonce_reply, msg) key_part = notsecure32_encode(ct) reply.add_answer(dnslib.RR(req_name, 16, ttl=0, rdata=dnslib.TXT(b"".join((base, key_part))))) return reply else: rec = self.store.get(user_name) if not rec: reply.header.rcode = dnslib.RCODE.NXDOMAIN return reply else: reply.add_answer(dnslib.RR(req_name, 16, ttl=0, rdata=dnslib.TXT(rec.record(0) .encode("utf8")))) return reply elif question.qtype == 6: self.update_soa() reply.add_answer(self.soa) return reply elif question.qtype == 2: for name in self.authority_list: reply.add_answer(dnslib.RR(req_name, 2, ttl=86400, rdata=dnslib.NS(name.encode("utf8")) )) return reply elif question.qtype == 1 and self.home_addresses: for ip in self.home_addresses: reply.add_answer(dnslib.RR(req_name, 1, ttl=3600, rdata=dnslib.A(ip))) elif question.qtype == 28 and self.home_addresses_6: for ip in self.home_addresses_6: reply.add_answer(dnslib.RR(req_name, 28, ttl=3600, rdata=dnslib.AAAA(ip))) else: reply.header.rcode = dnslib.RCODE.NXDOMAIN return reply return reply
def override(self, packet): dns_record = dnslib.DNSRecord.parse(packet) if str(dns_record.q.qname).lower() in overrides and dns_record.q.qtype == dnslib.QTYPE.A: dns_record.rr = [dnslib.RR(rname=dns_record.q.qname, rtype=dnslib.QTYPE.A, rclass=1, ttl=TTL, rdata=dnslib.A(overrides[str(dns_record.q.qname).lower()]))] print 'overrride', dns_record.rr[0] ''' while True: change = False for i in range(0, len(dns_record.rr)): if str(dns_record.rr[i].rname).lower() in overrides: if dns_record.rr[i].rtype == dnslib.QTYPE.A and str(dns_record.rr[i].rdata) != overrides[str(dns_record.rr[i].rname).lower()]: dns_record.rr[i].rdata = dnslib.A(overrides[str(dns_record.rr[i].rname).lower()]) change = True print dns_record.rr[i] if dns_record.rr[i].rtype == dnslib.QTYPE.CNAME and str(dns_record.rr[i].rdata).lower() not in overrides: overrides[str(dns_record.rr[i].rdata).lower()] = overrides[str(dns_record.rr[i].rname).lower()] change = True print dns_record.rr[i] if not change: break ''' return dns_record.pack()
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()