Exemplo n.º 1
0
 def parse(cls, packet):
     """
         Parse DNS packet data and return DNSRecord instance
         Recursively parses sections (calling appropriate parse method)
     """
     buffer = DNSBufferExt(packet)
     try:
         header = DNSHeader.parse(buffer)
         questions = []
         rr = []
         auth = []
         ar = []
         for i in range(header.q):
             questions.append(DNSQuestion.parse(buffer))
         for i in range(header.a):
             rr.append(RR.parse(buffer))
         for i in range(header.auth):
             auth.append(RR.parse(buffer))
         for i in range(header.ar):
             ar.append(RR.parse(buffer))
         return cls(header, questions, rr, auth=auth, ar=ar)
     except DNSError:
         raise
     except (BufferError, BimapError) as e:
         raise DNSError(f"Error unpacking DNSRecord [offset={buffer.offset:d}]: {e}")
Exemplo n.º 2
0
    def query(self, qname, qtype="A", qclass="IN"):
        qtype = QTYPE.reverse[qtype]
        qclass = CLASS.reverse[qclass]

        q = DNSRecord(q=DNSQuestion(qname, qtype, qclass))

        self.fire(write((self.server, self.port), q.pack()))
Exemplo n.º 3
0
    def switched_to(self, environment):
        rtype, current_val = self.current_value
        wanted_val = self.environments[environment]

        if set(current_val) != set(wanted_val):
            raise BespinError("The current value in ultradns is different than the specified value for this environment"
                , environment = environment
                , ultradns_has = current_val
                , specified = wanted_val
                )

        log.info("Seeing if %s has switched to %s(%s)", self.domain, environment, current_val)
        if rtype == "A":
            info = socket.getaddrinfo(self.domain, 80)
            found = [sockaddr[0] for _, _, _, _, sockaddr in info]
            if set(found) == set(current_val):
                return True
            else:
                log.info("Current value is %s", list(set(found)))

        if rtype == "CNAME":
            answer = DNSRecord.parse(DNSRecord(q=DNSQuestion(self.domain, QTYPE.CNAME)).send("8.8.8.8", 53)).short()
            if not answer:
                raise BespinError("couldn't resolve the domain", domain=self.domain)

            if answer == current_val[0]:
                return True
            else:
                log.info("Current value is %s", answer)

        return False
Exemplo n.º 4
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 []
Exemplo n.º 5
0
def take_from_cache(key, ident):
    name = '.'.join(key.split('.')[:-1])
    header = DNSHeader(id=ident, aa=0, qr=1, ra=1, rcode=0)
    question = DNSQuestion(name, REV_TYPES_DICT[key.split('.')[-1]])
    answer = DNSRecord(header=header, q=question)
    for rec in cache[key]:
        answer.add_answer(rec)
    return answer.pack()
Exemplo n.º 6
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)
Exemplo n.º 7
0
 def generate_response(self, ip, query, q_id):
     if type(ip) == str:
         record = DNSRecord(
             DNSHeader(id=q_id, qr=1, aa=1, ra=1),
             q=DNSQuestion(query),
             a=RR(query, rdata=A(ip)),
         )
         return record
     else:
         record = DNSRecord(
             DNSHeader(id=q_id, qr=1, aa=1, ra=1),
             q=DNSQuestion(query),
             a=RR(query, rdata=A(ip[0].address)),
         )
         for ip_obj in ip[1:]:
             record.add_answer(RR(query, QTYPE.A, rdata=A(ip_obj.address)))
         return record
Exemplo n.º 8
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)
Exemplo n.º 9
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 []
Exemplo n.º 10
0
def construct_response(quest_rec, response, rec_id):
    dns_hdr = DNSHeader(id=rec_id, qr=1, aa=1, ra=1)
    dns_q = DNSQuestion(quest_rec)
    reply = DNSRecord(dns_hdr, q=dns_q)

    for rr_idx in range(response.ancount):
        reply.add_answer(
            RR(quest_rec,
               rdata=A(response.an[rr_idx].rdata),
               ttl=response.an.ttl))

    return reply
Exemplo n.º 11
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)
Exemplo n.º 12
0
    def query(self, sub_domain):
        qname = self.domain.add(sub_domain)
        q = DNSRecord(q=DNSQuestion(qname=qname, qtype=QTYPE.CNAME))
        logger.debug('DNS Query:\n{q}'.format(q=q))
        rp = q.send(self.ns, self.ns_port)
        r = DNSRecord.parse(rp)
        logger.debug('DNS Response:\n{r}'.format(r=r))

        try:
            rr = r.rr[0].rdata.label.label
        except:
            rr = (b'error', b'client')
        return rr
Exemplo n.º 13
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 []
Exemplo n.º 14
0
 async def __forward_query(self, request, addr):
     """
     本服务没查到,转发查询到其他DNS服务器
     :return:
     """
     qname = str(request.q.qname)
     qtype = request.q.qtype
     qclass = request.q.qclass
     lookup = DNSRecord(q=DNSQuestion(qname, qtype, qclass))
     id = lookup.header.id
     self.peers[id] = addr
     self.requests[id] = request
     self.transport.sendto(lookup.pack(),
                           (random.choice(config.forward_dns), 53))
     self.logger.info("<<<>>> Froward")
Exemplo n.º 15
0
 def read(self, peer, data):
     try:
         self.fire(query(peer, DNSRecord.parse(data)))
     except:
         # Handle non latin characters, and respond with SERVFAIL
         data = customParse(data)
         printOut(peer, data['qtype'], data['q'], 'SERVFAIL')
         reply = DNSRecord(DNSHeader(id=data['id'],
                                     qr=1,
                                     aa=1,
                                     ra=1,
                                     rcode=2,
                                     qtype=data['qtype']),
                           q=DNSQuestion(data['q']))
         self.fire(write(peer, reply.pack()))
Exemplo n.º 16
0
    def lookup(self, qname, qclass="IN", qtype="A"):
        channel = uuid()

        client = Client(self.server, self.port, channel=channel).register(self)

        yield self.wait("ready", channel)

        self.fire(
            write(
                (self.server, self.port),
                DNSRecord(q=DNSQuestion(
                    qname, qclass=CLASS[qclass], qtype=QTYPE[qtype])).pack()))

        yield (yield self.wait("response", channel))

        client.unregister()
        yield self.wait("unregistered", channel)
        del client
Exemplo n.º 17
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
Exemplo n.º 18
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
Exemplo n.º 19
0
 def conn_tfo(self, job, config):  # pylint: disable=unused-argument
     if self.args.connect == "http":
         curlopts = {CURLOPT_TCP_FASTOPEN: 1}
         return connect_http(self.source, job, self.args.timeout, curlopts)
     elif self.args.connect == "https":
         curlopts = {CURLOPT_TCP_FASTOPEN: 1}
         return connect_https(self.source, job, self.args.timeout, curlopts)
     elif self.args.connect == "dnstcp":
         try:
             q = PSDNSRecord(q=DNSQuestion(job['domain'], QTYPE.A))
             data = q.pack()
             data = struct.pack("!H", len(data)) + data
             if ':' in job['dip']:
                 sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
                 sock.bind((self.source[1], 0))
             else:
                 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                 sock.bind((self.source[0], 0))
             # TODO: In non-blocking mode, this will always raise an EINPROGRESS
             # Should perform a blocking select afterwards, if it doesn't become available for
             # read then should fail it
             #sock.settimeout(self.args.timeout)
             sock.sendto(data, socket.MSG_FASTOPEN, (job['dip'], job['dp']))  # pylint: disable=no-member
             sp = sock.getsockname()[1]
             sock.close()
             return {'sp': sp, 'spdr_state': CONN_OK}
         except TimeoutError:
             return {
                 'sp': sock.getsockname()[1],
                 'spdr_state': CONN_TIMEOUT
             }
         except TypeError:  # Caused by not having a v4/v6 address when trying to bind
             return {'sp': 0, 'spdr_state': CONN_FAILED}
         except OSError:
             return {'sp': 0, 'spdr_state': CONN_FAILED}
     else:
         raise RuntimeError("Unknown connection mode specified")
Exemplo n.º 20
0
    def request(self, peer, request):
        qname = str(request.q.qname)
        qtype = request.q.qtype
        qclass = request.q.qclass

        key = (qname, qtype, qclass)

        if key in self.cache:
            self.logger.info(
                "Cached Request ({0:s}): {1:s} {2:s} {3:s}".format(
                    "{0:s}:{1:d}".format(*peer), CLASS.get(qclass),
                    QTYPE.get(qtype), qname))

            reply = request.reply()
            for rr in self.cache[key]:
                reply.add_answer(rr)
            self.fire(write(peer, reply.pack()))
            return

        if key in self.hosts:
            self.logger.info(
                "Local Hosts Request ({0:s}): {1:s} {2:s} {3:s}".format(
                    "{0:s}:{1:d}".format(*peer), CLASS.get(qclass),
                    QTYPE.get(qtype), qname))

            reply = request.reply()
            for rdata in self.hosts[key]:
                rr = RR(qname,
                        rclass=CLASS.IN,
                        rtype=QTYPE.AAAA if ":" in rdata else QTYPE.A,
                        rdata=AAAA(rdata) if ":" in rdata else A(rdata))
                reply.add_answer(rr)

            self.cache[key] = rr

            self.fire(write(peer, reply.pack()))

            return

        records = Record.objects.filter(rname=qname)

        if not records:
            self.logger.info(
                "Request ({0:s}): {1:s} {2:s} {3:s} -> {4:s}:{5:d}".format(
                    "{0:s}:{1:d}".format(*peer), CLASS.get(qclass),
                    QTYPE.get(qtype), qname, self.forward, 53))

            lookup = DNSRecord(q=DNSQuestion(qname, qtype, qclass))
            id = lookup.header.id
            self.peers[id] = peer
            self.requests[id] = request

            self.fire(write((self.forward, 53), lookup.pack()))

            return

        self.logger.info(
            "Authoritative Request ({0:s}): {1:s} {2:s} {3:s}".format(
                "{0:s}:{1:d}".format(*peer), CLASS.get(qclass),
                QTYPE.get(qtype), qname))

        rr = []
        reply = request.reply()

        if len(records) == 1 and records[0].rtype == CNAME:
            rr.append(records[0].rr)
            records = Record.objects.filter(rname=records[0].rdata)

        for record in records:
            rr.append(record.rr)

        reply.add_answer(*rr)

        self.cache[key] = rr

        self.fire(write(peer, reply.pack()))
Exemplo n.º 21
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()
Exemplo n.º 22
0
        NOTIFY=NOTIFY,
        services=[
            {
                "st": "upnp:rootdevice",
                "usn": "uuid:{uuid}::{st}"
            },
            {
                "st": "uuid:{uuid}",
                "usn": "uuid:{uuid}"
            },
            {
                "st": "urn:dial-multiscreen-org:device:dial:1",
                "usn": "uuid:{uuid}::{st}"
            },
            {
                "st": "urn:dial-multiscreen-org:service:dial:1",
                "usn": "uuid:{uuid}::{st}"
            },
        ])
]

mdns_services = [
    StaticMDNDService(
        response_generator=lambda query: get_chromecast_mdns_response(
            query, chromecast_ip, chromecast_uuid, chromecast_friendly_name,
            chromecast_bs, chromecast_cd),
        dns_question=DNSQuestion(qname="_googlecast._tcp.local",
                                 qtype=QTYPE.PTR,
                                 qclass=32769))
]
Exemplo n.º 23
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
    exit(1)

# Always use uppercase types
options.type = options.type.upper()

# Grab an mDNS socket ready for use
sock = get_mdns_socket()

# Create the DNS requests
for hostname in args:
    # Fix up the hostname if needed for the lookup.
    lookupHostname = hostname

    # Generate the DNS request.
    d = DNSRecord(DNSHeader(id=0, bitmap=0),
                  q=DNSQuestion(lookupHostname, getattr(QTYPE, options.type),
                                CLASS.IN))

    # Transmit.
    sock.sendto(d.pack(), (MDNS_DESTINATION, MDNS_PORT))

    # Timeout handler, just throws an exception.
    def timeout_handler(signum, frame):
        raise TimeoutException()

    signal.signal(signal.SIGALRM, timeout_handler)
    signal.alarm(5)  # Time out after 5 seconds.

    # Handle incoming responses until we find ours, or time out.
    try:
        while True:
            buf, remote = sock.recvfrom(8192)
Exemplo n.º 25
0
    def request(self, peer, request):
        qname = str(request.q.qname)
        qtype = request.q.qtype
        qclass = request.q.qclass

        key = (qname, qtype, qclass)

        if key in self.cache:
            self.logger.info(
                "Cached Request ({0:s}): {1:s} {2:s} {3:s}".format(
                    "{0:s}:{1:d}".format(*peer), CLASS.get(qclass),
                    QTYPE.get(qtype), qname))

            reply = request.reply()
            for rr in self.cache[key]:
                reply.add_answer(rr)
            self.fire(write(peer, reply.pack()))
            return

        if key in self.hosts:
            self.logger.info(
                "Local Hosts Request ({0:s}): {1:s} {2:s} {3:s}".format(
                    "{0:s}:{1:d}".format(*peer), CLASS.get(qclass),
                    QTYPE.get(qtype), qname))

            rr = [RR(qname, rdata=A(self.hosts[key]))]
            reply = request.reply()
            reply.add_answer(*rr)

            self.cache[key] = rr

            self.fire(write(peer, reply.pack()))

            return

        records = Record.objects.filter(rname=qname,
                                        rclass=qclass,
                                        rtype=qtype)

        if records:
            self.logger.info(
                "Authoritative Request ({0:s}): {1:s} {2:s} {3:s}".format(
                    "{0:s}:{1:d}".format(*peer), CLASS.get(qclass),
                    QTYPE.get(qtype), qname))

            rr = [record.rr for record in records]
            reply = request.reply()
            reply.add_answer(*rr)

            self.cache[key] = rr

            self.fire(write(peer, reply.pack()))

            return

        self.logger.info("Request ({0:s}): {1:s} {2:s} {3:s}".format(
            "{0:s}:{1:d}".format(*peer), CLASS.get(qclass), QTYPE.get(qtype),
            qname))

        lookup = DNSRecord(q=DNSQuestion(qname, qtype, qclass))
        id = lookup.header.id
        self.peers[id] = peer
        self.requests[id] = request

        self.fire(write((self.forward, 53), lookup.pack()))
Exemplo n.º 26
0
    def ready(self, client, bind):
        print("Ready! Bound to {0:s}:{1:d}".format(*bind), file=sys.stderr)

        request = DNSRecord(q=DNSQuestion(self.query))
        self.fire(write((self.server, self.port), request.pack()))
Exemplo n.º 27
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()
Exemplo n.º 28
0
 def send_error(self, q_id, query):
     return DNSRecord(DNSHeader(id=q_id, qr=1, aa=1, ra=1, rcode=3),
                      q=DNSQuestion(query))
Exemplo n.º 29
0
def dnstest():
    resp = DNSRecord(q=DNSQuestion("google.com")).send("127.0.0.1")
    assert str(resp.get_a().rdata) == LOCALADDR
Exemplo n.º 30
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