From: Remi Gacogne Date: Wed, 3 Sep 2025 07:23:20 +0000 (+0200) Subject: dnsdist: Add regression tests for packet cache and EDNS padding X-Git-Tag: rec-5.4.0-alpha1~247^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3045e30ec52e0eaf96ca84f6e75af17916bdfef4;p=thirdparty%2Fpdns.git dnsdist: Add regression tests for packet cache and EDNS padding Signed-off-by: Remi Gacogne --- diff --git a/regression-tests.dnsdist/paddingoption.py b/regression-tests.dnsdist/paddingoption.py new file mode 120000 index 0000000000..e4ef68e937 --- /dev/null +++ b/regression-tests.dnsdist/paddingoption.py @@ -0,0 +1 @@ +../regression-tests.recursor-dnssec/paddingoption.py \ No newline at end of file diff --git a/regression-tests.dnsdist/randompaddingoption.py b/regression-tests.dnsdist/randompaddingoption.py new file mode 100644 index 0000000000..b8a69cf4d3 --- /dev/null +++ b/regression-tests.dnsdist/randompaddingoption.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +import os +import paddingoption + +class RandomPaddingOption(paddingoption.PaddingOption): + """Implementation of rfc7830 using random bytes in the payload. + """ + + def __init__(self, numberOfBytes): + super(RandomPaddingOption, self).__init__(12) + self.numberOfBytes = numberOfBytes + + def to_wire(self, file=None): + """Create EDNS packet as defined in rfc7830 using random bytes in the payload.""" + + payload = os.urandom(self.numberOfBytes) + if file: + file.write(payload) + else: + return payload diff --git a/regression-tests.dnsdist/test_CachePadding.py b/regression-tests.dnsdist/test_CachePadding.py new file mode 100644 index 0000000000..3dc969d4e1 --- /dev/null +++ b/regression-tests.dnsdist/test_CachePadding.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python +import dns +import paddingoption +import randompaddingoption +from dnsdisttests import DNSDistTest, pickAvailablePort + +class TestCachePadding(DNSDistTest): + + _config_template = """ + pc = newPacketCache(100, {maxTTL=86400, minTTL=1}) + getPool(""):setCache(pc) + newServer{address="127.0.0.1:%d"} + """ + + def testCached(self): + """ + Cache padding + """ + name = 'padding.cache-padding.tests.powerdns.com.' + po = paddingoption.PaddingOption(64) + query = dns.message.make_query(name, 'A', want_dnssec=True, options=[po]) + response = dns.message.make_response(query) + rrset = dns.rrset.from_text(name, + 3600, + dns.rdataclass.IN, + dns.rdatatype.AAAA, + '::1') + response.answer.append(rrset) + + (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) + self.assertTrue(receivedQuery) + self.assertTrue(receivedResponse) + receivedQuery.id = query.id + self.assertEqual(query, receivedQuery) + self.assertEqual(receivedResponse, response) + + # identical query, should be cached + (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) + self.assertEqual(receivedResponse, response) + + # generate a new padding payload, with random bytes + rpo = randompaddingoption.RandomPaddingOption(64) + query = dns.message.make_query(name, 'A', want_dnssec=True, options=[rpo]) + response = dns.message.make_response(query) + response.answer.append(rrset) + + # identical query except for the padding content which should be skipped, should be cached + (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) + self.assertEqual(receivedResponse, response) + +class TestCacheNotSkippingPadding(DNSDistTest): + + _config_template = """ + -- only skip EDNS cookies, not padding + pc = newPacketCache(100, {maxTTL=86400, minTTL=1, skipOptions={10}}) + getPool(""):setCache(pc) + newServer{address="127.0.0.1:%d"} + """ + + def testCached(self): + """ + Cache padding: not skipping the padding + """ + name = 'not-skipping-padding.cache-padding.tests.powerdns.com.' + po = paddingoption.PaddingOption(64) + query = dns.message.make_query(name, 'A', want_dnssec=True, options=[po]) + response = dns.message.make_response(query) + rrset = dns.rrset.from_text(name, + 3600, + dns.rdataclass.IN, + dns.rdatatype.AAAA, + '::1') + response.answer.append(rrset) + + (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) + self.assertTrue(receivedQuery) + self.assertTrue(receivedResponse) + receivedQuery.id = query.id + self.assertEqual(query, receivedQuery) + self.assertEqual(receivedResponse, response) + + # identical query, should be cached + (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) + self.assertEqual(receivedResponse, response) + + # generate a new padding payload, with random bytes + rpo = randompaddingoption.RandomPaddingOption(64) + query = dns.message.make_query(name, 'A', want_dnssec=True, options=[rpo]) + response = dns.message.make_response(query) + + # identical query except for the padding content which should NOT be skipped, should NOT be cached + (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) + self.assertTrue(receivedQuery) + self.assertTrue(receivedResponse) + receivedQuery.id = query.id + self.assertEqual(query, receivedQuery) + self.assertEqual(receivedResponse, response) diff --git a/regression-tests.recursor-dnssec/paddingoption.py b/regression-tests.recursor-dnssec/paddingoption.py index 728da93a7d..db541f70c1 100644 --- a/regression-tests.recursor-dnssec/paddingoption.py +++ b/regression-tests.recursor-dnssec/paddingoption.py @@ -47,6 +47,9 @@ class PaddingOption(dns.edns.Option): self.numberOfBytes ) + def to_text(self): + return self.__repr__() + def __eq__(self, other): if not isinstance(other, PaddingOption): return False