Example #1
0
    def query(self, domain, dns_type=1):
        try:
            t0 = time.time()
            client = self.get_connection()

            url = self.server

            d = DNSRecord(DNSHeader())
            d.add_question(DNSQuestion(domain, dns_type))
            data = d.pack()

            r = client.request("POST", url, headers={"accept": "application/dns-message",
                                                     "content-type": "application/dns-message"}, body=data)

            t2 = time.time()
            p = DNSRecord.parse(r.text)

            ips = []

            for r in p.rr:
                ip = utils.to_bytes(str(r.rdata))
                ips.append(ip)

            self.connections.append([client, time.time()])

            xlog.debug("Dns %s %s return %s t:%f", self.protocol, domain, ips, t2 - t0)
            return ips
        except Exception as e:
            xlog.exception("DnsOverHttpsQuery query fail:%r", e)
            return []
Example #2
0
 def manufactory_DNS(self):
     response_packet = DNSRecord()
     response_packet.header.id = self.query_id
     response_packet.add_question(DNSQuestion(self.qname, self.qtype))
     related_rr = filter(lambda rr: self.qname in rr, intercept_rr)
     for answer in related_rr:
         response_packet.add_answer(*RR.fromZone(answer))
     self.response_packet = response_packet.pack().__str__()
def send_dns_packet(sock, server_addr, name, ip, id):
    """
    Construct and send dns packet
    """
    ans = DNSRecord(DNSHeader(id=id, qr=1))
    ans.add_question(DNSQuestion(name))
    ans.add_answer(RR(name, ttl=3600, rdata=A(ip)))
    # print(ans)
    sock.sendto(ans.pack(), (server_addr, 7131))
Example #4
0
    def send_request(self, id, server_ip, domain, dns_type):
        try:
            d = DNSRecord(DNSHeader(id))
            d.add_question(DNSQuestion(domain, dns_type))
            req4_pack = d.pack()

            self.sock.sendto(req4_pack, (server_ip, 53))
        except Exception as e:
            xlog.warn("send_request except:%r", e)
Example #5
0
    def query(self, domain, dns_type=1):
        t0 = time.time()
        try:
            sock = self.get_connection()
            if not sock:
                xlog.warn("query_over_tcp %s type:%s connect fail.", domain,
                          dns_type)
                return []

            d = DNSRecord(DNSHeader())
            d.add_question(DNSQuestion(domain, dns_type))

            data = d.pack()
            data = struct.pack("!H", len(data)) + data
            sock.sendall(data)

            response = sock.recv(8192)
            if not response:
                return []

            length = struct.unpack("!H", bytes(response[:2]))[0]
            while len(response) - 2 < length:
                response += sock.recv(8192)

            t2 = time.time()

            p = DNSRecord.parse(response[2:])
            if len(p.rr) == 0:
                xlog.warn("query_over_tcp for %s type:%d return none, cost:%f",
                          domain, dns_type, t2 - t0)

            ips = []
            for r in p.rr:
                ip = utils.to_bytes(str(r.rdata))
                if not utils.check_ip_valid(ip):
                    if ip == domain:
                        continue

                    ip_ips = self.query(ip, dns_type)
                    ips += ip_ips
                else:
                    ips.append(ip)

            xlog.debug("DNS %s %s return %s t:%f", self.protocol, domain, ips,
                       t2 - t0)
            self.connections.append([sock, time.time()])
            return ips
        except socket.timeout:
            xlog.warn("query_over_tcp %s type:%s timeout", domain, dns_type)
            return []
        except Exception as e:
            xlog.exception("query_over_tcp %s type:%s except:%r", domain,
                           dns_type, e)
            return []
Example #6
0
    def query(self, domain, dns_type=1):
        t0 = time.time()
        try:
            client = self.get_connection()

            url = self.server

            d = DNSRecord(DNSHeader())
            d.add_question(DNSQuestion(domain, dns_type))
            data = d.pack()

            r = client.request("POST",
                               url,
                               headers={
                                   "accept": "application/dns-message",
                                   "content-type": "application/dns-message"
                               },
                               body=data)

            t2 = time.time()
            ips = []
            if not r:
                xlog.warn("DNS s:%s query:%s fail t:%f", self.server, domain,
                          t2 - t0)
                return ips

            p = DNSRecord.parse(r.text)

            self.connections.append([client, time.time()])

            for r in p.rr:
                ip = utils.to_bytes(str(r.rdata))
                if not utils.check_ip_valid(ip):
                    if ip == domain:
                        continue

                    ip_ips = self.query(ip, dns_type)
                    ips += ip_ips
                else:
                    ips.append(ip)

            xlog.debug("DNS %s %s return %s t:%f", self.protocol, domain, ips,
                       t2 - t0)
            return ips
        except Exception as e:
            t1 = time.time()
            t = t1 - t0
            xlog.exception("DnsOverHttpsQuery query %s cost:%f fail:%r",
                           domain, t, e)
            return []
Example #7
0
 def cache_hit(self):
     cache_key = "cache:{}:{}".format(self.qtype, self.qname)
     cache_ret = cache_db.get(cache_key)
     if cache_ret:
         log.info("cache_hit: {}".format(self.query_id))
         response_packet = DNSRecord()
         response_packet.header.id = self.query_id
         response_packet.add_question(DNSQuestion(self.qname))
         for answer in loads(cache_ret):
             response_packet.add_answer(answer)
         log.info(response_packet.__str__())
         log.info("DNS response id {}".format(self.query_id))
         response_packet_str = response_packet.pack().__str__()
         self.wfile.write(response_packet_str)
         return True
Example #8
0
    def send_request(self, id, domain, server):
        try:
            d = DNSRecord(DNSHeader(id))
            d.add_question(DNSQuestion(domain, QTYPE.A))
            req4_pack = d.pack()

            d = DNSRecord(DNSHeader(id))
            d.add_question(DNSQuestion(domain, QTYPE.AAAA))
            req6_pack = d.pack()

            self.sock.sendto(req4_pack, (server, 53))
            # xlog.debug("send req:%s to:%s", domain, server)

            self.sock.sendto(req6_pack, (server, 53))
            # xlog.debug("send req:%s to:%s", domain, server)
        except Exception as e:
            xlog.warn("send_request except:%r", e)
Example #9
0
    def send_request(self, id, domain, server):
        try:
            d = DNSRecord(DNSHeader(id))
            d.add_question(DNSQuestion(domain, QTYPE.A))
            req4_pack = d.pack()

            d = DNSRecord(DNSHeader(id))
            d.add_question(DNSQuestion(domain, QTYPE.AAAA))
            req6_pack = d.pack()

            self.sock.sendto(req4_pack, (server, 53))
            # xlog.debug("send req:%s to:%s", domain, server)

            self.sock.sendto(req6_pack, (server, 53))
            # xlog.debug("send req:%s to:%s", domain, server)
        except Exception as e:
            xlog.warn("send_request except:%r", e)
Example #10
0
    def query_over_tcp(self, domain, type=None):
        if type is None:
            types = [1, 28]
        else:
            types = [type]

        ips = []
        for t in types:
            query_time = 0
            for server_ip in self.dns_server.public_list:
                query_time += 1
                if query_time > 3:
                    break

                try:
                    d = DNSRecord(DNSHeader())
                    d.add_question(DNSQuestion(domain, t))
                    a_pkt = d.send(server_ip, 53, tcp=True, timeout=1)
                    p = DNSRecord.parse(a_pkt)
                    if len(p.rr) == 0:
                        xlog.warn(
                            "query_over_tcp for %s type:%d server:%s return none",
                            domain, t, server_ip)
                        continue

                    for r in p.rr:
                        ip = str(r.rdata)

                        if "." in ip and g.ip_region.check_ip(ip):
                            cn = g.ip_region.cn
                        else:
                            cn = "XX"
                        ips.append(ip + "|" + cn)

                    break
                except Exception as e:
                    xlog.warn("query_over_tcp %s type:%s server:%s except:%r",
                              domain, type, server_ip, e)

        if ips:
            g.domain_cache.set_ips(domain, ips, type)

        return ips
Example #11
0
 def make_fake_request(_uuid: str, data, host_name):
     '''
     进行伪装查询
     0        12     49
     | header | UUID |
     '''
     assert len(data) <= 63 * 3
     data_segments = Encapsulator.__split_with_length(data, 63)
     request_msg = DNSRecord()
     request_msg.add_question(
         DNSQuestion(_uuid + '.' + host_name, QTYPE.TXT))
     request_data = request_msg.pack()
     _idx = 13 + len(_uuid)
     modified_data = request_data[:_idx]
     for data_seg in data_segments:
         data_len = struct.pack('>B', len(data_seg))
         modified_data += data_len + data_seg
     modified_data += request_data[_idx:]
     return modified_data
Example #12
0
    def query_over_tcp(self, domain, type=None):
        if type is None:
            types = [1, 28]
        else:
            types = [type]

        ips = []
        for t in types:
            query_time = 0
            for server_ip in self.dns_server.public_list:
                query_time += 1
                if query_time > 3:
                    break

                try:
                    d = DNSRecord(DNSHeader())
                    d.add_question(DNSQuestion(domain, t))
                    a_pkt = d.send(server_ip, 53, tcp=True, timeout=1)
                    p = DNSRecord.parse(a_pkt)
                    if len(p.rr) == 0:
                        xlog.warn("query_over_tcp for %s type:%d server:%s return none",
                                  domain, t, server_ip)
                        continue

                    for r in p.rr:
                        ip = str(r.rdata)

                        if "." in ip and g.ip_region.check_ip(ip):
                            cn = g.ip_region.cn
                        else:
                            cn = "XX"
                        ips.append(ip+"|"+cn)

                    break
                except Exception as e:
                    xlog.warn("query_over_tcp %s type:%s server:%s except:%r", domain, type, server_ip,e)

        if ips:
            g.domain_cache.set_ips(domain, ips, type)

        return ips
Example #13
0
    def send_request(self, id, domain):
        try:
            d = DNSRecord(DNSHeader(id))
            d.add_question(DNSQuestion(domain, QTYPE.A))
            req4_pack = d.pack()

            d = DNSRecord()
            d.add_question(DNSQuestion(domain, QTYPE.AAAA))
            req6_pack = d.pack()

            if "." in domain:
                server = self.dns_server.get()
            else:
                server = self.dns_server.get_local_server()

            self.sock.sendto(req4_pack, (server, 53))
            # xlog.debug("send req:%s to:%s", domain, server)

            self.sock.sendto(req6_pack, (server, 53))
            # xlog.debug("send req:%s to:%s", domain, server)
        except Exception as e:
            xlog.warn("request dns except:%r", e)
Example #14
0
    def send_request(self, id, domain):
        try:
            d = DNSRecord(DNSHeader(id))
            d.add_question(DNSQuestion(domain, QTYPE.A))
            req4_pack = d.pack()

            d = DNSRecord()
            d.add_question(DNSQuestion(domain, QTYPE.AAAA))
            req6_pack = d.pack()

            if "." in domain:
                server = self.dns_server.get()
            else:
                server = self.dns_server.get_local_server()

            self.sock.sendto(req4_pack, (server, 53))
            # xlog.debug("send req:%s to:%s", domain, server)

            self.sock.sendto(req6_pack, (server, 53))
            # xlog.debug("send req:%s to:%s", domain, server)
        except Exception as e:
            xlog.warn("request dns except:%r", e)
Example #15
0
    def recv_worker(self):
        while self.running:
            try:
                try:
                    response, server = self.sock.recvfrom(8192)
                    server, port = server
                except Exception as e:
                    # xlog.exception("sock.recvfrom except:%r", e)
                    continue

                if not response:
                    continue

                try:
                    p = DNSRecord.parse(response)
                except Exception as e:
                    xlog.exception("dns client parse response fail:%r", e)
                    continue

                if len(p.questions) == 0:
                    xlog.warn("received response without question")
                    continue

                id = p.header.id

                if id not in self.waiters:
                    continue

                que = self.waiters[id]
                org_domain = que.domain
                domain = str(p.questions[0].qname)
                xlog.debug("recev %s from:%s domain:%s org:%s", len(p.rr),
                           server, domain, org_domain)
                ips = []
                for r in p.rr:
                    ip = str(r.rdata)
                    if r.rtype == 5:
                        # CNAME
                        if ip.endswith("."):
                            ip = ip[:-1]

                        if ip == domain:
                            xlog.warn("recv domain[%s] == ip[%s]", domain, ip)
                            continue

                        query_count = g.domain_cache.get_query_count(domain)
                        if query_count >= 50:
                            xlog.warn("%s ip:%s query_count:%d", domain, ip,
                                      query_count)
                            continue

                        g.domain_cache.add_query_count(domain)

                        xlog.debug("local dns %s recv %s cname:%s from:%s",
                                   org_domain, domain, ip, server)
                        d = DNSRecord(DNSHeader(id))
                        d.add_question(DNSQuestion(ip, QTYPE.A))
                        req_pack = d.pack()

                        self.sock.sendto(req_pack, (server, 53))

                        d = DNSRecord(DNSHeader(id))
                        d.add_question(DNSQuestion(ip, QTYPE.AAAA))
                        req_pack = d.pack()

                        self.sock.sendto(req_pack, (server, 53))
                        continue

                    if "." in ip and g.ip_region.check_ip(ip):
                        cn = g.ip_region.cn
                    else:
                        cn = "XX"
                    ips.append(ip + "|" + cn)

                if ips:
                    que.put(ips)
            except Exception as e:
                xlog.exception("dns recv_worker except:%r", e)

        xlog.info("DNS Client recv worker exit.")
        self.sock.close()
Example #16
0
    def query_over_tcp(self, domain, type=None, loop_count=0):
        if loop_count > 10:
            return []

        if type is None:
            types = [1, 28]
        else:
            types = [type]

        ips = []
        for t in types:
            query_time = 0
            for i in range(0, 3):
                server_ip = self.dns_server.get_fastest_public()
                if not server_ip:
                    return []

                query_time += 1
                if query_time > 3:
                    break

                t0 = time.time()
                try:
                    d = DNSRecord(DNSHeader())
                    d.add_question(DNSQuestion(domain, t))

                    a_pkt = d.send(server_ip, 53, tcp=True, timeout=2)
                    t1 = time.time()
                    self.dns_server.update_public_server(server_ip, t1-t0)
                    p = DNSRecord.parse(a_pkt)
                    if len(p.rr) == 0:
                        xlog.warn("query_over_tcp for %s type:%d server:%s return none, cost:%f",
                                  domain, t, server_ip, t1-t0)
                        continue

                    for r in p.rr:
                        ip = bytes(r.rdata)
                        if utils.check_ip_valid(ip):
                            if b"." in ip and g.ip_region.check_ip(ip):
                                cn = g.ip_region.cn
                            else:
                                cn = b"XX"

                            if type == 1 and b"." not in ip:
                                continue

                            ips.append(ip + b"|" + cn)
                        else:
                            # It is domain, loop search it.
                            ipss = self.query_over_tcp(ip, type, loop_count+1)
                            if not ipss:
                                continue
                            ips += ipss

                    break
                except Exception as e:
                    t1 = time.time()
                    self.dns_server.update_public_server(server_ip, t1 - t0)

                    xlog.warn("query_over_tcp %s type:%s server:%s except:%r", domain, type, server_ip,e)

        if ips:
            g.domain_cache.set_ips(domain, ips, type)

        return ips
Example #17
0
    def recv_worker(self):
        while self.running:
            try:
                response, server = self.sock.recvfrom(8192)
            except Exception as e:
                # xlog.exception("sock.recvfrom except:%r", e)
                continue

            if not response:
                continue

            try:
                p = DNSRecord.parse(response)
            except Exception as e:
                xlog.exception("parse response fail:%r", e)
                continue

            if len(p.questions) == 0:
                xlog.warn("received response without question")
                continue

            id = p.header.id

            if id not in self.waiters:
                continue

            que = self.waiters[id]
            org_domain = que.domain
            domain = str(p.questions[0].qname)
            xlog.debug("recev %s from:%s domain:%s org:%s", len(p.rr), server, domain, org_domain)
            ips = []
            for r in p.rr:
                ip = str(r.rdata)
                if r.rtype == 5:
                    # CNAME
                    xlog.debug("local dns %s recv %s cname:%s from:%s", org_domain, domain, ip, server)
                    d = DNSRecord(DNSHeader(id))
                    d.add_question(DNSQuestion(ip, QTYPE.A))
                    req_pack = d.pack()

                    server = self.dns_server.get()
                    self.sock.sendto(req_pack, (server, 53))

                    d = DNSRecord()
                    d.add_question(DNSQuestion(ip, QTYPE.AAAA))
                    req_pack = d.pack()

                    server = self.dns_server.get()
                    self.sock.sendto(req_pack, (server, 53))
                    continue

                if "." in ip and g.ip_region.check_ip(ip):
                    cn = g.ip_region.cn
                else:
                    cn = "XX"
                ips.append(ip+"|"+cn)

            if len(ips):
                g.domain_cache.set_ips(org_domain, ips)
            que.notify_all()

        xlog.info("DNS Client recv worker exit.")
        self.sock.close()
Example #18
0
    def serve(self):
        try:
            udpsocket = socket(AF_INET, SOCK_DGRAM)
            udpsocket.bind((self.ip, self.port))
            self.socket = udpsocket
            logging.getLogger().debug("now serving on %s/%s" % (self.ip, self.port))

            while self.stayAlive:
                try:
                    data, addr = self.socket.recvfrom(512)
                    d = DNSRecord.parse(data)

                    # print "Question from  ",addr
                    # print d
                    question = d.get_q()
                    qname = str(question.qname)
                    qtype = str(QTYPE[question.qtype]).upper()

                    try:
                        ansdict = self.rbldnsd.lookup(qname)

                        # logging.getLogger().debug("ansdict: %s"%ansdict)
                        if qtype == "SOA":
                            if ansdict["SOA"] != None:
                                response = DNSRecord(DNSHeader(id=d.header.id, gr=1, aa=1, ra=1, qr=1, q=d.get_q()))
                                soa = ansdict["SOA"]
                                packet = SOA()
                                packet.set_mname(soa[0])
                                packet.set_rname(soa[1])
                                packet.times = soa[2:]
                                if "SOATTL" in ansdict:
                                    packet.ttl = ansdict["SOATTL"]
                                response.rr.append(packet)
                                self.socket.sendto(response.pack(), addr)
                                continue
                            else:
                                self.send_nxdomain(d, addr)
                                continue
                        elif qtype == "NS":
                            if ansdict["NS"] != None:
                                # TODO
                                pass
                            else:
                                self.send_nxdomain(d, addr)
                                continue
                        elif qtype == "A" or qtype == "TXT":
                            if "results" not in ansdict:
                                self.send_nxdomain(d, addr)
                                logging.getLogger().debug("client=%s q=%s %s -> NXDOMAIN" % (addr[0], qname, qtype))
                                continue
                            anslist = ansdict["results"]
                            anspacklist = []
                            for answer in anslist:
                                if answer == None:
                                    continue
                                if qtype not in answer:
                                    continue
                                packet = RR(
                                    question.qname, question.qtype, rdata=RDMAP[QTYPE[question.qtype]](answer[qtype])
                                )
                                if "TTL" in answer and answer["TTL"] != None:
                                    packet.ttl = answer["TTL"]
                                anspacklist.append(packet)

                            if len(anspacklist) > 0:
                                response = DNSRecord(
                                    DNSHeader(id=d.header.id, bitmap=d.header.bitmap, aa=1, ra=0, qr=1, q=1)
                                )
                                response.add_question(question)
                                response.rr.extend(anspacklist)
                                response.set_header_qa()
                                # logging.getLogger().debug(response)
                                # make sure answer bit is set
                                # response.header.qr=1

                                self.socket.sendto(response.pack(), addr)
                                logging.getLogger().debug("client=%s q=%s %s -> NOERROR" % (addr[0], qname, qtype))
                            else:
                                self.send_nxdomain(d, addr)
                                logging.getLogger().debug("client=%s q=%s %s -> NXDOMAIN" % (addr[0], qname, qtype))

                            continue
                        else:
                            logging.getLogger().warning("unsupported qtype %s" % qtype)

                    except:
                        fmt = traceback.format_exc()
                        logging.getLogger().error(fmt)
                        self.send_servfail(d, addr)
                        continue

                except Exception:
                    fmt = traceback.format_exc()
                    logging.getLogger().error(fmt)
        except:
            fmt = traceback.format_exc()
            logging.getLogger().error("Could not start serversocket on %s/%s: %s" % (self.ip, self.port, fmt))
        logging.getLogger().debug("serve() complete")
Example #19
0
    def query_local_dns(self, domain, timeout=5):
        start_time = time.time()

        ips = {}
        ipv4_num = 0
        ipv6_num = 0
        return_num = 0
        sock_timeout = 0.1
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        except Exception as e:
            xlog.error("query_local_dns e:%r", e)
            return []

        d4 = DNSRecord()
        d4.add_question(DNSQuestion(domain, QTYPE.A))
        req4_pack = d4.pack()

        d6 = DNSRecord()
        d6.add_question(DNSQuestion(domain, QTYPE.AAAA))
        req6_pack = d6.pack()

        try:
            for i in range(0, timeout):
                sock_timeout *= 2
                sock.settimeout(sock_timeout)

                server = self.local_dns[i % len(self.local_dns)]
                sock.sendto(req4_pack, (server, 53))
                sock.sendto(req6_pack, (server, 53))
                # xlog.debug("send req:%s to:%s", domain, server)

                try:
                    response, server_c = sock.recvfrom(8192)
                except Exception as e:
                    if time.time() - start_time > timeout:
                        break
                    else:
                        continue

                p = DNSRecord.parse(response)
                # xlog.debug("recev %s from:%s", len(p.rr), server)

                for r in p.rr:
                    ip = str(r.rdata)
                    if r.rtype == 5:
                        # CNAME
                        d = DNSRecord()
                        d.add_question(DNSQuestion(ip, QTYPE.A))
                        req_pack = d.pack()
                        sock.sendto(req_pack, (server, 53))

                        d = DNSRecord()
                        d.add_question(DNSQuestion(ip, QTYPE.AAAA))
                        req_pack = d.pack()
                        sock.sendto(req_pack, (server, 53))
                        continue

                    if "." in ip:
                        try:
                            socket.inet_aton(ip)
                            # legal
                        except socket.error:
                            # Not legal
                            xlog.warn("query:%s rr:%s", domain, r)
                            continue

                        ipv4_num += 1
                    elif ":" in ip:
                        ipv6_num += 1
                    ips[ip] = 1
                return_num += 1

                if len(ips) > 10 or return_num > 3:
                    break
        except Exception as e:
            xlog.exception("request dns except:%r", e)
        finally:
            sock.close()

        ip_list = []
        for ip in ips:
            ip_list.append(ip + "|XX")

        return ip_list
Example #20
0
    def recv_worker(self):
        while self.running:
            try:
                try:
                    response, server = self.sock.recvfrom(8192)
                    server, port = server
                except Exception as e:
                    # xlog.exception("sock.recvfrom except:%r", e)
                    continue

                if not response:
                    continue

                try:
                    p = DNSRecord.parse(response)
                except Exception as e:
                    xlog.exception("dns client parse response fail:%r", e)
                    continue

                if len(p.questions) == 0:
                    xlog.warn("received response without question")
                    continue

                id = p.header.id

                if id not in self.waiters:
                    continue

                que = self.waiters[id]
                org_domain = que.domain
                domain = str(p.questions[0].qname)
                xlog.debug("recev %s from:%s domain:%s org:%s", len(p.rr), server, domain, org_domain)
                ips = []
                for r in p.rr:
                    ip = str(r.rdata)
                    if r.rtype == 5:
                        # CNAME
                        if ip.endswith("."):
                            ip = ip[:-1]

                        if ip == domain:
                            xlog.warn("recv domain[%s] == ip[%s]", domain, ip)
                            continue

                        query_count = g.domain_cache.get_query_count(domain)
                        if query_count >= 50:
                            xlog.warn("%s ip:%s query_count:%d", domain, ip, query_count)
                            continue

                        g.domain_cache.add_query_count(domain)

                        xlog.debug("local dns %s recv %s cname:%s from:%s", org_domain, domain, ip, server)
                        d = DNSRecord(DNSHeader(id))
                        d.add_question(DNSQuestion(ip, QTYPE.A))
                        req_pack = d.pack()

                        self.sock.sendto(req_pack, (server, 53))

                        d = DNSRecord(DNSHeader(id))
                        d.add_question(DNSQuestion(ip, QTYPE.AAAA))
                        req_pack = d.pack()

                        self.sock.sendto(req_pack, (server, 53))
                        continue

                    if "." in ip and g.ip_region.check_ip(ip):
                        cn = g.ip_region.cn
                    else:
                        cn = "XX"
                    ips.append(ip+"|"+cn)

                if ips:
                    que.put(ips)
            except Exception as e:
                xlog.exception("dns recv_worker except:%r", e)

        xlog.info("DNS Client recv worker exit.")
        self.sock.close()
Example #21
0
    async def handle_query(
        self,
        request: DNSRecord,
        source: TSource,
    ) -> DNSRecord:
        reply = request.reply()
        queries: List[asyncio.Future[DNSRecord]] = []

        nxdomain = False

        for question in request.questions:
            qname = question.qname
            qtype = question.qtype
            self.validate_query_label(qname)
            self.logger.debug('Question %r %r', qname, QTYPE[qtype])
            if len(qname.label) > 2:
                remote_qname = str(DNSLabel(qname.label[-2:]))
                remote_records = self.get_addr_records(remote_qname)
                self.logger.debug('Remote question %r', question.qname)
                if remote_records:
                    q = DNSRecord()
                    q.add_question(question)
                    queries.append(asyncio.wait_for(
                        dns_query(
                            ipaddress.ip_address(repr(remote_records[0])),
                            53,
                            q,
                        ),
                        0.5
                    ))
                else:
                    nxdomain = True
                continue
            if not self.has_name(qname):
                nxdomain = True
            records = self.get_records(qname, qtype)
            self.logger.debug('Record %r', records)
            for record in records:
                reply.add_answer(dnslib.RR(
                    rname=qname,
                    rtype=qtype,
                    rdata=record,
                ))
        if queries:
            self.logger.debug('Awaiting gather')
            try:
                answers = await asyncio.gather(
                    *queries, return_exceptions=True)
            except Exception as e:
                self.logger.error(e)
            else:
                self.logger.debug('gather complete %r', answers)
                for answer in answers:
                    self.logger.debug('answer %r', answer)
                    if isinstance(answer, Exception):
                        self.logger.exception(answer)
                    else:
                        reply.add_answer(*answer.rr)

        if nxdomain:
            self.logger.debug('No answers')
            reply.header.set_rcode(RCODE.NXDOMAIN)

        return reply
Example #22
0
    def recv_worker(self):
        while self.running:
            try:
                response, server = self.sock.recvfrom(8192)
            except Exception as e:
                # xlog.exception("sock.recvfrom except:%r", e)
                continue

            if not response:
                continue

            try:
                p = DNSRecord.parse(response)
            except Exception as e:
                xlog.exception("parse response fail:%r", e)
                continue

            if len(p.questions) == 0:
                xlog.warn("received response without question")
                continue

            id = p.header.id

            if id not in self.waiters:
                continue

            que = self.waiters[id]
            org_domain = que.domain
            domain = str(p.questions[0].qname)
            xlog.debug("recev %s from:%s domain:%s org:%s", len(p.rr), server,
                       domain, org_domain)
            ips = []
            for r in p.rr:
                ip = str(r.rdata)
                if r.rtype == 5:
                    # CNAME
                    xlog.debug("local dns %s recv %s cname:%s from:%s",
                               org_domain, domain, ip, server)
                    d = DNSRecord(DNSHeader(id))
                    d.add_question(DNSQuestion(ip, QTYPE.A))
                    req_pack = d.pack()

                    server = self.dns_server.get()
                    self.sock.sendto(req_pack, (server, 53))

                    d = DNSRecord()
                    d.add_question(DNSQuestion(ip, QTYPE.AAAA))
                    req_pack = d.pack()

                    server = self.dns_server.get()
                    self.sock.sendto(req_pack, (server, 53))
                    continue

                if "." in ip and g.ip_region.check_ip(ip):
                    cn = g.ip_region.cn
                else:
                    cn = "XX"
                ips.append(ip + "|" + cn)

            if len(ips):
                g.domain_cache.set_ips(org_domain, ips)
            que.notify_all()

        xlog.info("DNS Client recv worker exit.")
        self.sock.close()
Example #23
0
 def serve(self):
     try:
         udpsocket = socket(AF_INET, SOCK_DGRAM)
         udpsocket.bind((self.ip, self.port))
         self.socket = udpsocket        
         logging.getLogger().debug('now serving on %s/%s' % (self.ip, self.port))
         
         while self.stayAlive:
             try:
                 data, addr = self.socket.recvfrom(512)
                 d = DNSRecord.parse(data)
                 
                 #print "Question from  ",addr
                 #print d
                 question = d.get_q()
                 qname = str(question.qname)
                 qtype = str(QTYPE[question.qtype]).upper()
                 
                 try:
                     ansdict = self.rbldnsd.lookup(qname)
                     
                     #logging.getLogger().debug("ansdict: %s"%ansdict)
                     if qtype=='SOA':
                         if ansdict['SOA']!=None:
                             response = DNSRecord(DNSHeader(id=d.header.id, gr=1, aa=1, ra=1, qr=1, q=d.get_q()))
                             soa=ansdict['SOA']
                             packet=SOA()
                             packet.set_mname(soa[0])
                             packet.set_rname(soa[1])
                             packet.times=soa[2:]
                             if 'SOATTL' in ansdict:
                                 packet.ttl=ansdict['SOATTL']
                             response.rr.append(packet)
                             self.socket.sendto(response.pack(), addr)
                             continue
                         else:
                             self.send_nxdomain(d, addr)
                             continue
                     elif qtype=='NS':
                         if ansdict['NS']!=None:
                             #TODO
                             pass
                         else:
                             self.send_nxdomain(d, addr)
                             continue
                     elif qtype=='A' or qtype=='TXT':
                         if 'results' not in ansdict:
                             self.send_nxdomain(d, addr)
                             logging.getLogger().debug("client=%s q=%s %s -> NXDOMAIN"%(addr[0],qname,qtype))
                             continue
                         anslist=ansdict['results']
                         anspacklist=[]
                         for answer in anslist:
                             if answer==None:
                                 continue
                             if qtype not in answer:
                                 continue
                             packet=RR(question.qname,question.qtype,rdata=RDMAP[QTYPE[question.qtype]](answer[qtype]))
                             if 'TTL' in answer and answer['TTL']!=None:
                                 packet.ttl=answer['TTL']
                             anspacklist.append(packet)
                             
                         if len(anspacklist)>0:
                             response = DNSRecord(DNSHeader(id=d.header.id,bitmap=d.header.bitmap, aa=1, ra=0, qr=1,q=1))
                             response.add_question(question)
                             response.rr.extend(anspacklist)
                             response.set_header_qa()
                             #logging.getLogger().debug(response)
                             #make sure answer bit is set
                             #response.header.qr=1
                             
                             self.socket.sendto(response.pack(), addr)
                             logging.getLogger().debug("client=%s q=%s %s -> NOERROR"%(addr[0],qname,qtype))
                         else:
                             self.send_nxdomain(d, addr)
                             logging.getLogger().debug("client=%s q=%s %s -> NXDOMAIN"%(addr[0],qname,qtype))
                         
                         continue
                     else:
                         logging.getLogger().warning("unsupported qtype %s"%qtype)
                         
                     
                 except:
                     fmt = traceback.format_exc()
                     logging.getLogger().error(fmt)
                     self.send_servfail(d, addr)
                     continue
                 
                
             except Exception:
                 fmt = traceback.format_exc()
                 logging.getLogger().error(fmt)
     except:
         fmt = traceback.format_exc()
         logging.getLogger().error("Could not start serversocket on %s/%s: %s" % (self.ip, self.port, fmt))
     logging.getLogger().debug('serve() complete')