예제 #1
0
    def testMultiCookiesECS6FFI(self):
        """
        EDNS Options: Two Cookies + ECS6 (FFI)
        """
        name = 'multiplecookies-ecs6.ednsoptions.tests.powerdns.com.'
        eco1 = cookiesoption.CookiesOption(b'deadbeef', b'deadbeef')
        ecso = clientsubnetoption.ClientSubnetOption('2001:DB8::1', 128)
        eco2 = cookiesoption.CookiesOption(b'deadc0de', b'deadc0de')
        query = dns.message.make_query(name,
                                       'A',
                                       'IN',
                                       use_edns=True,
                                       payload=4096,
                                       options=[eco1, ecso, eco2])
        response = dns.message.make_response(query)
        rrset = dns.rrset.from_text(name, 3600, dns.rdataclass.IN,
                                    dns.rdatatype.A, '127.0.0.1')
        response.answer.append(rrset)

        for method in ("sendUDPQuery", "sendTCPQuery"):
            sender = getattr(self, method)
            (receivedQuery, receivedResponse) = sender(query, response)
            self.assertTrue(receivedQuery)
            self.assertTrue(receivedResponse)
            receivedQuery.id = query.id
            self.assertEquals(receivedQuery, query)
            self.assertEquals(receivedResponse, response)
예제 #2
0
    def testCookie(self):
        """
        EDNS Options: Cookie
        """
        name = 'cookie.ednsoptions.tests.powerdns.com.'
        eco = cookiesoption.CookiesOption(b'deadbeef', b'deadbeef')
        query = dns.message.make_query(name,
                                       'A',
                                       'IN',
                                       use_edns=True,
                                       payload=4096,
                                       options=[eco])
        response = dns.message.make_response(query)
        rrset = dns.rrset.from_text(name, 3600, dns.rdataclass.IN,
                                    dns.rdatatype.A, '127.0.0.1')
        response.answer.append(rrset)

        for method in ("sendUDPQuery", "sendTCPQuery"):
            sender = getattr(self, method)
            (receivedQuery, receivedResponse) = sender(query, response)
            self.assertTrue(receivedQuery)
            self.assertTrue(receivedResponse)
            receivedQuery.id = query.id
            self.assertEquals(receivedQuery, query)
            self.assertEquals(receivedResponse, response)
예제 #3
0
    def testECS6Cookie(self):
        """
        EDNS Options: Cookie + ECS6 (adding ECS)
        """
        name = 'cookie-ecs6.ednsoptions-ecs.tests.powerdns.com.'
        eco = cookiesoption.CookiesOption(b'deadbeef', b'deadbeef')
        ecso = clientsubnetoption.ClientSubnetOption('2001:DB8::1', 128)
        query = dns.message.make_query(name,
                                       'A',
                                       'IN',
                                       use_edns=True,
                                       payload=4096,
                                       options=[ecso, eco])
        ecsoResponse = clientsubnetoption.ClientSubnetOption('2001:DB8::1',
                                                             128,
                                                             scope=56)
        response = dns.message.make_response(query)
        response.use_edns(edns=True, payload=4096, options=[ecsoResponse])
        rrset = dns.rrset.from_text(name, 3600, dns.rdataclass.IN,
                                    dns.rdatatype.A, '127.0.0.1')
        response.answer.append(rrset)

        for method in ("sendUDPQuery", "sendTCPQuery"):
            sender = getattr(self, method)
            (receivedQuery, receivedResponse) = sender(query, response)
            self.assertTrue(receivedQuery)
            self.assertTrue(receivedResponse)
            receivedQuery.id = query.id
            self.checkQueryEDNSWithECS(query, receivedQuery, 1)
            self.checkResponseEDNSWithECS(response, receivedResponse)
예제 #4
0
    def testECS6Cookie(self):
        """
        EDNS Options: Cookie + ECS6
        """
        name = 'cookie-ecs6.ednsoptions.tests.powerdns.com.'
        eco = cookiesoption.CookiesOption('deadbeef', 'deadbeef')
        ecso = clientsubnetoption.ClientSubnetOption('2001:DB8::1', 128)
        query = dns.message.make_query(name,
                                       'A',
                                       'IN',
                                       use_edns=True,
                                       payload=4096,
                                       options=[ecso, eco])
        response = dns.message.make_response(query)
        rrset = dns.rrset.from_text(name, 3600, dns.rdataclass.IN,
                                    dns.rdatatype.A, '127.0.0.1')
        response.answer.append(rrset)

        (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = query.id
        self.assertEquals(receivedQuery, query)
        self.assertEquals(receivedResponse, response)

        (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = query.id
        self.assertEquals(receivedQuery, query)
        self.assertEquals(receivedResponse, response)
예제 #5
0
    def testWithEDNSNoECSResponseWithCookiesThenECS(self):
        """
        ECS: Existing EDNS without ECS (BE returning Cookies then ECS options)

        Send a query with EDNS but no ECS value.
        Check that the query received by the responder
        has a valid ECS value and that the response
        received from dnsdist contains an EDNS pseudo-RR.
        This time the response returned by the backend contains
        one cookies then one ECS option.
        """
        name = 'withednsnoecs.bereturnscookiesthenecs.ecs.tests.powerdns.com.'
        ecso = clientsubnetoption.ClientSubnetOption('127.0.0.1', 24)
        query = dns.message.make_query(name,
                                       'A',
                                       'IN',
                                       use_edns=True,
                                       payload=4096)
        expectedQuery = dns.message.make_query(name,
                                               'A',
                                               'IN',
                                               use_edns=True,
                                               payload=4096,
                                               options=[ecso])
        response = dns.message.make_response(expectedQuery)
        ecoResponse = cookiesoption.CookiesOption(b'deadbeef', b'deadbeef')
        ecsoResponse = clientsubnetoption.ClientSubnetOption('127.0.0.1',
                                                             24,
                                                             scope=24)
        response.use_edns(edns=True,
                          payload=4096,
                          options=[ecoResponse, ecsoResponse])
        expectedResponse = dns.message.make_response(query)
        rrset = dns.rrset.from_text(name, 3600, dns.rdataclass.IN,
                                    dns.rdatatype.A, '127.0.0.1')
        response.answer.append(rrset)
        expectedResponse.answer.append(rrset)
        expectedResponse.use_edns(edns=True,
                                  payload=4096,
                                  options=[ecoResponse])

        (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = expectedQuery.id
        self.checkQueryEDNSWithECS(expectedQuery, receivedQuery)
        self.checkResponseEDNSWithoutECS(expectedResponse,
                                         receivedResponse,
                                         withCookies=1)

        (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = expectedQuery.id
        self.checkQueryEDNSWithECS(expectedQuery, receivedQuery)
        self.checkResponseEDNSWithoutECS(expectedResponse,
                                         receivedResponse,
                                         withCookies=1)
예제 #6
0
    def testEDNSOptions(self):
        name = 'gettag-ednsoptions.lua.'
        subnet = '192.0.2.255'
        subnetMask = 32
        ecso = clientsubnetoption.ClientSubnetOption(subnet, subnetMask)
        eco1 = cookiesoption.CookiesOption(b'deadbeef', b'deadbeef')
        eco2 = cookiesoption.CookiesOption(b'deadc0de', b'deadc0de')

        expected = [
            dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.1'),
            dns.rrset.from_text_list(name, 0, dns.rdataclass.IN, 'TXT', [name, 'gettag-qtype-1', 'edns-subnet-' + subnet + '/' + str(subnetMask),
                                                                         'ednsoption-10-count-2', 'ednsoption-10-total-len-32',
                                                                         'ednsoption-8-count-1', 'ednsoption-8-total-len-8'
                                                                        ]),
            ]
        query = dns.message.make_query(name, 'A', want_dnssec=True, options=[eco1,ecso,eco2])
        query.flags |= dns.flags.CD
        res = self.sendUDPQuery(query)
        self.assertResponseMatches(query, expected, res)
예제 #7
0
    def testCookie(self):
        """
        EDNS Options: Cookie (adding ECS)
        """
        name = 'cookie.ednsoptions-ecs.tests.powerdns.com.'
        eco = cookiesoption.CookiesOption('deadbeef', 'deadbeef')
        query = dns.message.make_query(name,
                                       'A',
                                       'IN',
                                       use_edns=True,
                                       payload=4096,
                                       options=[eco])
        ecso = clientsubnetoption.ClientSubnetOption('127.0.0.1', 24)
        expectedQuery = dns.message.make_query(name,
                                               'A',
                                               'IN',
                                               use_edns=True,
                                               options=[eco, ecso],
                                               payload=512)
        response = dns.message.make_response(query)
        rrset = dns.rrset.from_text(name, 3600, dns.rdataclass.IN,
                                    dns.rdatatype.A, '127.0.0.1')
        response.answer.append(rrset)

        (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = expectedQuery.id
        self.checkQueryEDNSWithECS(expectedQuery, receivedQuery, 1)
        self.checkResponseEDNSWithoutECS(response, receivedResponse)

        (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
        self.assertTrue(receivedQuery)
        self.assertTrue(receivedResponse)
        receivedQuery.id = expectedQuery.id
        self.checkQueryEDNSWithECS(expectedQuery, receivedQuery, 1)
        self.checkResponseEDNSWithoutECS(response, receivedResponse)
    def testPacketCache(self):
        # first query, no cookie
        qname = 'a.example.'
        query = dns.message.make_query(qname, 'A', want_dnssec=True)
        expected = dns.rrset.from_text(qname, 0, dns.rdataclass.IN, 'A',
                                       '192.0.2.42')

        for method in ("sendUDPQuery", "sendTCPQuery"):
            sender = getattr(self, method)
            res = sender(query)
            self.assertRcodeEqual(res, dns.rcode.NOERROR)
            self.assertRRsetInAnswer(res, expected)

        self.checkPacketCacheMetrics(0, 1)

        # we should get a hit over UDP this time
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(1, 1)

        eco1 = cookiesoption.CookiesOption(b'deadbeef', b'deadbeef')
        eco2 = cookiesoption.CookiesOption(b'deadc0de', b'deadc0de')
        ecso1 = clientsubnetoption.ClientSubnetOption('192.0.2.1', 32)
        ecso2 = clientsubnetoption.ClientSubnetOption('192.0.2.2', 32)

        # we add a cookie, should not match anymore
        query = dns.message.make_query(qname,
                                       'A',
                                       want_dnssec=True,
                                       options=[eco1])
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(1, 2)

        # same cookie, should match
        query = dns.message.make_query(qname,
                                       'A',
                                       want_dnssec=True,
                                       options=[eco1])
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(2, 2)

        # different cookie, should still match
        query = dns.message.make_query(qname,
                                       'A',
                                       want_dnssec=True,
                                       options=[eco2])
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(3, 2)

        # first cookie but with an ECS option, should not match
        query = dns.message.make_query(qname,
                                       'A',
                                       want_dnssec=True,
                                       options=[eco1, ecso1])
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(3, 3)

        # different cookie but same ECS option, should match
        query = dns.message.make_query(qname,
                                       'A',
                                       want_dnssec=True,
                                       options=[eco2, ecso1])
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(4, 3)

        # first cookie but different ECS option, should still match (we ignore EDNS Client Subnet
        # in the recursor's packet cache, but ECS-specific responses are not cached
        query = dns.message.make_query(qname,
                                       'A',
                                       want_dnssec=True,
                                       options=[eco1, ecso2])
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(5, 3)
예제 #9
0
    def testPacketCache(self):
        # first query, no cookie
        qname = 'a.example.'
        query = dns.message.make_query(qname, 'A', want_dnssec=True)
        expected = dns.rrset.from_text(qname, 0, dns.rdataclass.IN, 'A', '192.0.2.42')

        for method in ("sendUDPQuery", "sendTCPQuery"):
            sender = getattr(self, method)
            res = sender(query)
            self.assertRcodeEqual(res, dns.rcode.NOERROR)
            self.assertRRsetInAnswer(res, expected)

        self.checkPacketCacheMetrics(0, 2)

        # we should get a hit over UDP this time
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(1, 2)

        # we should get a hit over TCP this time
        res = self.sendTCPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(2, 2)

        eco1 = cookiesoption.CookiesOption(b'deadbeef', b'deadbeef')
        eco2 = cookiesoption.CookiesOption(b'deadc0de', b'deadc0de')
        ecso1 = clientsubnetoption.ClientSubnetOption('192.0.2.1', 32)
        ecso2 = clientsubnetoption.ClientSubnetOption('192.0.2.2', 32)

        # we add a cookie, should not match anymore
        query = dns.message.make_query(qname, 'A', want_dnssec=True, options=[eco1])
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(2, 3)

        # same cookie, should match
        query = dns.message.make_query(qname, 'A', want_dnssec=True, options=[eco1])
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(3, 3)

        # different cookie, should still match
        query = dns.message.make_query(qname, 'A', want_dnssec=True, options=[eco2])
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(4, 3)

        # first cookie but with an ECS option, should not match
        query = dns.message.make_query(qname, 'A', want_dnssec=True, options=[eco1, ecso1])
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(4, 4)

        # different cookie but same ECS option, should match
        query = dns.message.make_query(qname, 'A', want_dnssec=True, options=[eco2, ecso1])
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(5, 4)

        # first cookie but different ECS option, should still match (we ignore EDNS Client Subnet
        # in the recursor's packet cache, but ECS-specific responses are not cached
        query = dns.message.make_query(qname, 'A', want_dnssec=True, options=[eco1, ecso2])
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.assertRRsetInAnswer(res, expected)
        self.checkPacketCacheMetrics(6, 4)

        # NXDomain should get default packetcache TTL (10)
        query = dns.message.make_query('nxdomain.example.', 'A', want_dnssec=True)
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NXDOMAIN)
        self.checkPacketCacheMetrics(6, 5)

        # NoData should get default packetcache TTL (10)
        query = dns.message.make_query('a.example.', 'AAAA', want_dnssec=True)
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.NOERROR)
        self.checkPacketCacheMetrics(6, 6)

        # ServFail should get ServFail TTL (5)
        query = dns.message.make_query('f.example.', 'A', want_dnssec=True)
        res = self.sendUDPQuery(query)
        self.assertRcodeEqual(res, dns.rcode.SERVFAIL)
        self.checkPacketCacheMetrics(6, 7)

        # We peek into the cache to check TTLs and allow TTLs to be one lower than inserted since the clock might have ticked
        rec_controlCmd = [os.environ['RECCONTROL'],
                          '--config-dir=%s' % 'configs/' + self._confdir,
                          'dump-cache', '-']
        try:
            ret = subprocess.check_output(rec_controlCmd, stderr=subprocess.STDOUT)
            self.assertTrue((b"a.example. 10 A  ; tag 0 udp\n" in ret) or (b"a.example. 9 A  ; tag 0 udp\n" in ret))
            self.assertTrue((b"nxdomain.example. 10 A  ; tag 0 udp\n" in ret) or (b"nxdomain.example. 9 A  ; tag 0 udp\n" in ret))
            self.assertTrue((b"a.example. 10 AAAA  ; tag 0 udp\n" in ret) or (b"a.example. 9 AAAA  ; tag 0 udp\n" in ret))
            self.assertTrue((b"f.example. 5 A  ; tag 0 udp\n" in ret) or (b"f.example. 4 A  ; tag 0 udp\n" in ret))

        except subprocess.CalledProcessError as e:
            print(e.output)
            raise