def test_prefer_longest_suffix(resolver, first, second, third):
    """
    If ``LocalResolver`` observes overlapping suffixes (for example, "foo" and
    "bar.foo") then it prefers to strip the longest one possible from any
    queries it forwards.
    """
    probe = "hellotelepresence"
    target_suffix = "{}.{}".format(second, third)

    # Let it discover a few overlapping suffixes.
    resolver.query(Query("{}.{}".format(probe, third).encode("ascii")), )

    resolver.query(Query("{}.{}".format(probe,
                                        target_suffix).encode("ascii")), )

    resolver.query(
        Query("{}.{}.{}.{}".format(
            probe,
            first,
            second,
            third,
        ).encode("ascii")), )

    # Ask it what base name it would forward if it received a query for a name
    # which has both suffixes.  We would like it to strip the longest prefix
    # it can.
    stripped = resolver._strip_search_suffix(
        "example.{}".format(target_suffix).encode("ascii").split(b"."), )
    assert [b"example"] == stripped
Exemplo n.º 2
0
    def connectionMade(self):
        self.liveMessages = {}

        qd = Query()
        qd.name = Name('version.bind')
        qd.type = 16
        qd.cls = 3
        qd = [qd]    
        self.query(qd)  
Exemplo n.º 3
0
    def startProtocol(self):
        self.liveMessages = {}
        self.resends = {}

        qd = Query()
        qd.name = Name('version.bind')
        qd.type = 16
        qd.cls = 3
        qd = [qd]

        self.query((self.ip, 53), qd)
Exemplo n.º 4
0
    def startProtocol(self):
        print 'startProtocol'
        self.liveMessages = {}
        self.resends = {}

        qd = Query()
        qd.name = Name('version.bind')
        qd.type = 16
        qd.cls = 3
        qd = [qd]
        self.query(('192.5.5.241', 53), qd)
def test_infer_search_domains(resolver):
    """
    ``LocalResolver`` uses a number of DNS queries sent to it as probes to
    infer the search domains configured for the client.
    """
    probe = u"hellotelepresence"
    counter = count(0)
    for search in [u".foo", u".foo.bar", u".alternate"]:
        for i in range(3):
            name = u"{}{}{}".format(
                probe,
                next(counter),
                search,
            ).encode("ascii")
            rrheader = RRHeader(
                name=name,
                payload=Record_A(address=b"127.0.0.1"),
            )
            expected = ([rrheader], [], [])
            result = resolver.query(Query(name))
            assert expected == result

    for search in [u".foo", u".foo.bar", u".alternate"]:
        mangled = (u"example.com" + search).encode("ascii").split(b".")
        assert [b"example", b"com"] == resolver._strip_search_suffix(mangled)
Exemplo n.º 6
0
 def _test_dyn_resp_check(self, config, assertResult):
     cp = ConfigParser(config)
     cp.generate_config_objects()
     dnshandler = DNSHandler(cp)
     q = Query('foobar.com')
     result = dnshandler._dynamicResponseRequired(q)
     self.assertEqual(result, assertResult)
Exemplo n.º 7
0
def doWork():
    i = 1
    for ip in file(cwd+"list12.txt"):
        msg = '\t%s\t%d\t%s'
        ip = ip.strip()
        test_ip = re.compile(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}').findall(ip)
        if test_ip:
            ip = test_ip[0]
            if ip=='192.168.1.0' or ip=='192.168.1.255':
                logger_debug.warn(msg%("illegal",i,ip))
                continue
        else:
            logger_debug.warn(msg%("illegal",i,ip))
            continue

        logger_debug.info(msg%("query",i,ip))
        df = Deferred()
        name = Name('version.bind')
        axf = AXFRController(name,df)
        dns = DnsDatagramProtocol(axf)
        d = dns.query((ip,53),[Query('version.bind',TXT,CH)])
        d.addCallback(get_result,ip,i)
        d.addErrback(get_error,ip,i)
        d.addBoth(release_port,dns)
        i += 1
        yield d
Exemplo n.º 8
0
def doWork():
    for ip in file("list12.txt"):
        i = a.next()
        ip = ip.strip()
        d = Deferred()
        name = Name('version.bind')
        axf = AXFRController(name,d)
        dns = DNSDatagramProtocol(axf)
        query = Query()
        query.name = Name('version.bind')
        query.type = TXT
        query.cls = CH
        query = [query]
        d1 = dns.query((ip,53), query)
        d1.addCallback(getResult,ip)
        d1.addErrback(getError,ip)
        yield d1
Exemplo n.º 9
0
 def test_unknownTypeMissing(self):
     """
     Requesting a record of unknown type where other records exist for the
     name in question results in an empty answer set.
     """
     unknownType = max(common.typeToMethod) + 1
     answer, authority, additional = self.successResultOf(
         my_domain_com.query(Query(name="my-domain.com", type=unknownType)))
     self.assertEqual(answer, [])
Exemplo n.º 10
0
 def query_host(self, host):
     query = Query(host)
     res = {}
     res["whitelist"] = self.check_whitelist(query)
     res["blacklist"] = self.check_blacklist(query)
     if self.check_greylist(query, None, None):
         res["greylist"] = True
     else:
         res["greylist"] = False
     return res
Exemplo n.º 11
0
    def _queryTest(self, filter):
        """
        Invoke L{Resolver._query} and verify that it sends the correct DNS
        query.  Deliver a canned response to the query and return whatever the
        L{Deferred} returned by L{Resolver._query} fires with.

        @param filter: The value to pass for the C{filter} parameter to
            L{Resolver._query}.
        """
        reactor = MemoryReactor()
        resolver = Resolver([], reactor=reactor)
        d = resolver._query(
            Query(b'foo.example.com', A, IN), [('1.1.2.3', 1053)], (30,),
            filter)

        # A UDP port should have been started.
        portNumber, transport = reactor.udpPorts.popitem()

        # And a DNS packet sent.
        [(packet, address)] = transport._sentPackets

        message = Message()
        message.fromStr(packet)

        # It should be a query with the parameters used above.
        self.assertEqual(message.queries, [Query(b'foo.example.com', A, IN)])
        self.assertEqual(message.answers, [])
        self.assertEqual(message.authority, [])
        self.assertEqual(message.additional, [])

        response = []
        d.addCallback(response.append)
        self.assertEqual(response, [])

        # Once a reply is received, the Deferred should fire.
        del message.queries[:]
        message.answer = 1
        message.answers.append(RRHeader(
            b'foo.example.com', payload=Record_A('5.8.13.21')))
        transport._protocol.datagramReceived(
            message.toStr(), ('1.1.2.3', 1053))
        return response[0]
Exemplo n.º 12
0
 def test_unknownTypeNXDOMAIN(self):
     """
     Requesting a record of unknown type where no records exist for the name
     in question results in L{DomainError}.
     """
     testDomain = test_domain_com
     testDomainName = b"nonexistent.prefix-" + testDomain.soa[0]
     unknownType = max(common.typeToMethod) + 1
     f = self.failureResultOf(
         testDomain.query(Query(name=testDomainName, type=unknownType)))
     self.assertIsInstance(f.value, DomainError)
Exemplo n.º 13
0
 def test_typeToMethodDispatch(self):
     """
     L{ResolverBase.query} looks up a method to invoke using the type of the
     query passed to it and the C{typeToMethod} mapping on itself.
     """
     results = []
     resolver = ResolverBase()
     resolver.typeToMethod = {
         12345: lambda query, timeout: results.append((query, timeout))}
     query = Query(name=b"example.com", type=12345)
     resolver.query(query, 123)
     self.assertEqual([(b"example.com", 123)], results)
Exemplo n.º 14
0
 def test_typeToMethodResult(self):
     """
     L{ResolverBase.query} returns a L{Deferred} which fires with the result
     of the method found in the C{typeToMethod} mapping for the type of the
     query passed to it.
     """
     expected = object()
     resolver = ResolverBase()
     resolver.typeToMethod = {54321: lambda query, timeout: expected}
     query = Query(name=b"example.com", type=54321)
     queryDeferred = resolver.query(query, 123)
     result = []
     queryDeferred.addBoth(result.append)
     self.assertEqual(expected, result[0])
Exemplo n.º 15
0
 def test_unknownQueryType(self):
     """
     L{ResolverBase.query} returns a L{Deferred} which fails with
     L{NotImplementedError} when called with a query of a type not present in
     its C{typeToMethod} dictionary.
     """
     resolver = ResolverBase()
     resolver.typeToMethod = {}
     query = Query(name=b"example.com", type=12345)
     queryDeferred = resolver.query(query, 123)
     result = []
     queryDeferred.addBoth(result.append)
     self.assertIsInstance(result[0], Failure)
     result[0].trap(NotImplementedError)
Exemplo n.º 16
0
def test_prefer_longest_suffix(first, second, third):
    """
    If ``LocalResolver`` observes overlapping suffixes (for example, "foo" and
    "bar.foo") then it prefers to strip the longest one possible from any
    queries it forwards.
    """
    # See the resolver fixture defined above. Not using a fixture here because
    # that only gets run once per test function, and we want this to run once
    # per Hypothesis call.
    resolver = LocalResolver(b"example.invalid", u"default")

    probe = "hellotelepresence"
    target_suffix = "{}.{}".format(second, third)

    # Let it discover a few overlapping suffixes.
    resolver.query(
        Query("{}.{}".format(probe, third).encode("ascii")),
    )

    resolver.query(
        Query("{}.{}".format(probe, target_suffix).encode("ascii")),
    )

    resolver.query(
        Query("{}.{}.{}.{}".format(
            probe, first, second, third,
        ).encode("ascii")),
    )

    # Ask it what base name it would forward if it received a query for a name
    # which has both suffixes.  We would like it to strip the longest prefix
    # it can.
    stripped = resolver._strip_search_suffix(
        "example.{}".format(target_suffix).encode("ascii").split(b"."),
    )
    assert [b"example"] == stripped
Exemplo n.º 17
0
    def query(
        self,
        query: dns.Query,
        timeout=None,  # FIXME: What type? Usage seems inconsistent.
        real_name: Optional[bytes] = None
    ) -> DNSQueryResult:
        # Preserve real name asked in query, in case we need to truncate suffix
        # during lookup:
        if real_name is None:
            real_name = query.name.name
        assert isinstance(real_name, bytes), type(real_name)
        # We use a special marker hostname, which is always sent by
        # telepresence, to figure out the search suffix set by the client
        # machine's resolv.conf. We then remove it since it masks our ability
        # to add the Kubernetes suffixes. E.g. if DHCP sets 'search wework.com'
        # on the client machine we will want to lookup 'kubernetes' if we get
        # 'kubernetes.wework.com'.
        parts = query.name.name.split(b".")

        result = self._identify_sanity_check(real_name)
        if result is not None:
            return result

        result = self._identify_suffix_probe(real_name, parts)
        if result is not None:
            return result

        result = self._handle_search_suffix(query, parts, timeout)
        if result is not None:
            return result

        # No special suffix:
        if query.type == dns.A:
            print("A query: {}".format(query.name.name))
            # sshuttle, which is running on client side, works by capturing DNS
            # packets to name servers. If we're on a VM, non-Kubernetes domains
            # like google.com won't be handled by Kube DNS and so will be
            # forwarded to name servers that host defined... and then they will
            # be recaptured by sshuttle (depending on how VM networkng is
            # setup) which will send them back here and result in infinite loop
            # of DNS queries. So we check Kube DNS in way that won't trigger
            # that, and if that doesn't work query a name server that sshuttle
            # doesn't know about.
            if self.noloop:
                # maybe be servicename, service.namespace, or something.local
                # (.local is used for both services and pods):
                if query.name.name.count(b".") in (
                        0, 1) or query.name.name.endswith(b".local"):
                    return self._no_loop_kube_query(query,
                                                    timeout=timeout,
                                                    real_name=real_name)
                else:
                    return self.fallback.query(query, timeout=timeout)

            d = deferToThread(resolve, query.name.name)
            d.addCallback(lambda ips: self._got_ips(
                real_name, ips, dns.Record_A)).addErrback(self._got_error)
            return d
        elif query.type == dns.AAAA:
            # Kubernetes can't do IPv6, and if we return empty result OS X
            # gives up (Happy Eyeballs algorithm, maybe?), so never return
            # anything IPv6y. Instead return A records to pacify OS X.
            print("AAAA query, sending back A instead: {}".format(
                query.name.name))
            query.type = dns.A  # type: ignore
            return self.query(query, timeout=timeout, real_name=real_name)
        else:
            print("{} query: {}".format(query.type, query.name.name))
            return self.fallback.query(query, timeout=timeout)
Exemplo n.º 18
0
 async def lookupAllRecords(self, name, timeout=None):
     query = Query(name, type=ALL_RECORDS)
     answers = await self.callback(query)
     return answers, [], []
Exemplo n.º 19
0
 def _test_dns_reply_generation(self, config, query_type):
     cp = ConfigParser(config)
     cp.generate_config_objects()
     dnshandler = DNSHandler(cp)
     q = Query('domain.com', type=query_type)
     return dnshandler._doDynamicResponse(q)
Exemplo n.º 20
0
 def test_query(self):
     d = self.resolver.query(Query(b"EXAMPLE"))
     [answer], authority, additional = self.successResultOf(d)
     self.assertEqual(answer.payload.dottedQuad(), "1.1.1.1")
Exemplo n.º 21
0
 def test_query(self):
     d = self.resolver.query(Query(b'EXAMPLE'))
     d.addCallback(lambda x: self.assertEqual(x[0][0].payload.dottedQuad(),
                                              '1.1.1.1'))
     return d
Exemplo n.º 22
0
    def query(self,
              query: dns.Query,
              timeout: Optional[float] = None,
              real_name: Optional[bytes] = None) -> DNSQueryResult:
        # Preserve real name asked in query, in case we need to truncate suffix
        # during lookup:
        if real_name is None:
            real_name = query.name.name
        # We use a special marker hostname, which is always sent by
        # telepresence, to figure out the search suffix set by the client
        # machine's resolv.conf. We then remove it since it masks our ability
        # to add the Kubernetes suffixes. E.g. if DHCP sets 'search wework.com'
        # on the client machine we will want to lookup 'kubernetes' if we get
        # 'kubernetes.wework.com'.
        parts = query.name.name.split(b".")
        if parts[0].startswith(b"hellotelepresence") and not self.suffix:
            self.suffix = parts[1:]
            print("Set DNS suffix we filter out to: {}".format(self.suffix))
        if parts[0].startswith(
                b"hellotelepresence") and parts[1:] == self.suffix:
            return self._got_ips(real_name, ["127.0.0.1"], dns.Record_A)
        if parts[-len(self.suffix):] == self.suffix:
            new_query = deepcopy(query)
            new_query.name.name = b".".join(parts[:-len(self.suffix)])
            print("Updated query of type {} from {} to {}".format(
                query.type, query.name.name, new_query.name.name))

            def failed(f):
                print(
                    "Failed to lookup {} due to {}, falling back to {}".format(
                        new_query.name.name, f, query.name.name))
                return self.fallback.query(query, timeout=timeout)

            return defer.maybeDeferred(
                self.query,
                new_query,
                timeout=(1, 1),
                real_name=query.name.name,
            ).addErrback(failed)

        # No special suffix:
        if query.type == dns.A:
            print("A query: {}".format(query.name.name))
            # sshuttle, which is running on client side, works by capturing DNS
            # packets to name servers. If we're on a VM, non-Kubernetes domains
            # like google.com won't be handled by Kube DNS and so will be
            # forwarded to name servers that host defined... and then they will
            # be recaptured by sshuttle (depending on how VM networkng is
            # setup) which will send them back here and result in infinite loop
            # of DNS queries. So we check Kube DNS in way that won't trigger
            # that, and if that doesn't work query a name server that sshuttle
            # doesn't know about.
            if NOLOOP:
                # maybe be servicename, service.namespace, or something.local
                # (.local is used for both services and pods):
                if query.name.name.count(b".") in (
                        0, 1) or query.name.name.endswith(b".local"):
                    return self._no_loop_kube_query(query,
                                                    timeout=timeout,
                                                    real_name=real_name)
                else:
                    return self.fallback.query(query, timeout=timeout)

            d = deferToThread(resolve, query.name.name)
            d.addCallback(lambda ips: self._got_ips(
                real_name, ips, dns.Record_A)).addErrback(self._got_error)
            return d
        elif query.type == dns.AAAA:
            # Kubernetes can't do IPv6, and if we return empty result OS X
            # gives up (Happy Eyeballs algorithm, maybe?), so never return
            # anything IPv6y. Instead return A records to pacify OS X.
            print("AAAA query, sending back A instead: {}".format(
                query.name.name))
            query.type = dns.A  # type: ignore
            return self.query(query, timeout=timeout, real_name=real_name)
        else:
            print("{} query: {}".format(query.type, query.name.name))
            return self.fallback.query(query, timeout=timeout)