]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
rec: Add regression tests for Proxy Protocol / ECS interaction
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 19 Apr 2021 09:13:47 +0000 (11:13 +0200)
committerOtto <otto.moerbeek@open-xchange.com>
Mon, 10 May 2021 14:07:26 +0000 (16:07 +0200)
(cherry picked from commit 9166ee1b3fc9d5df9b93570d883cf154aa98e425)

regression-tests.recursor-dnssec/recursortests.py
regression-tests.recursor-dnssec/test_ECS.py
regression-tests.recursor-dnssec/test_ProxyProtocol.py

index 5051e2f5dabe61c67d91048612ce4e55246060a8..084697f4042c6787d556733ec89db6af8c6273f5 100644 (file)
@@ -13,6 +13,8 @@ import unittest
 import dns
 import dns.message
 
+from proxyprotocol import ProxyProtocol
+
 from eqdnsmessage import AssertEqualDNSMessageMixin
 
 
@@ -974,3 +976,59 @@ distributor-threads={threads}""".format(confdir=confdir,
         msg.flags += dns.flags.from_text('RD')
         msg.use_edns(edns=0, ednsflags=dns.flags.edns_from_text(ednsflags))
         return msg
+
+    @classmethod
+    def sendUDPQueryWithProxyProtocol(cls, query, v6, source, destination, sourcePort, destinationPort, values=[], timeout=2.0):
+        queryPayload = query.to_wire()
+        ppPayload = ProxyProtocol.getPayload(False, False, v6, source, destination, sourcePort, destinationPort, values)
+        payload = ppPayload + queryPayload
+
+        if timeout:
+            cls._sock.settimeout(timeout)
+
+        try:
+            cls._sock.send(payload)
+            data = cls._sock.recv(4096)
+        except socket.timeout:
+            data = None
+        finally:
+            if timeout:
+                cls._sock.settimeout(None)
+
+        message = None
+        if data:
+            message = dns.message.from_wire(data)
+        return message
+
+    @classmethod
+    def sendTCPQueryWithProxyProtocol(cls, query, v6, source, destination, sourcePort, destinationPort, values=[], timeout=2.0):
+        queryPayload = query.to_wire()
+        ppPayload = ProxyProtocol.getPayload(False, False, v6, source, destination, sourcePort, destinationPort, values)
+
+        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        if timeout:
+            sock.settimeout(timeout)
+
+        sock.connect(("127.0.0.1", cls._recursorPort))
+
+        try:
+            sock.send(ppPayload)
+            sock.send(struct.pack("!H", len(queryPayload)))
+            sock.send(queryPayload)
+            data = sock.recv(2)
+            if data:
+                (datalen,) = struct.unpack("!H", data)
+                data = sock.recv(datalen)
+        except socket.timeout as e:
+            print("Timeout: %s" % (str(e)))
+            data = None
+        except socket.error as e:
+            print("Network error: %s" % (str(e)))
+            data = None
+        finally:
+            sock.close()
+
+        message = None
+        if data:
+            message = dns.message.from_wire(data)
+        return message
index d1b80505fa6f409d621ac3ef60c33fc7e1c7db51..efed1a9321105638c7ee658df1a8513fdaa85738 100644 (file)
@@ -499,6 +499,98 @@ forward-zones=ecs-echo.example=%s.21
         query = dns.message.make_query(nameECS, 'TXT', 'IN', use_edns=True, options=[ecso], payload=512)
         self.sendECSQuery(query, expected)
 
+class testECSWithProxyProtocoldRecursorTest(ECSTest):
+    _confdir = 'ECSWithProxyProtocol'
+    _config_template = """
+    ecs-add-for=2001:db8::1/128
+    edns-subnet-allow-list=ecs-echo.example.
+    forward-zones=ecs-echo.example=%s.21
+    proxy-protocol-from=127.0.0.1/32
+    allow-from=2001:db8::1/128
+""" % (os.environ['PREFIX'])
+
+    def testProxyProtocolPlusECS(self):
+        qname = nameECS
+        expected = dns.rrset.from_text(qname, 0, dns.rdataclass.IN, 'TXT', '2001:db8::/56')
+
+        query = dns.message.make_query(qname, 'TXT', use_edns=True)
+        for method in ("sendUDPQueryWithProxyProtocol", "sendTCPQueryWithProxyProtocol"):
+            sender = getattr(self, method)
+            res = sender(query, True, '2001:db8::1', '2001:db8::2', 0, 65535)
+            self.assertRcodeEqual(res, dns.rcode.NOERROR)
+            self.assertRRsetInAnswer(res, expected)
+
+class testTooLargeToAddZeroScope(RecursorTest):
+
+    _confdir = 'TooLargeToAddZeroScope'
+    _config_template_default = """
+use-incoming-edns-subnet=yes
+dnssec=validate
+daemon=no
+trace=yes
+packetcache-ttl=0
+packetcache-servfail-ttl=0
+max-cache-ttl=15
+threads=1
+loglevel=9
+disable-syslog=yes
+log-common-errors=yes
+"""
+    _config_template = """
+    """
+    _lua_dns_script_file = """
+    function preresolve(dq)
+      if dq.qname == newDN('toolarge.ecs.') then
+        dq:addRecord(pdns.TXT, '%s', pdns.place.ANSWER)
+        return true
+      end
+      return false
+    end
+    """ % ('A'*447)
+
+    _roothints = None
+
+    @classmethod
+    def setUpClass(cls):
+
+        # we don't need all the auth stuff
+        cls.setUpSockets()
+        cls.startResponders()
+
+        confdir = os.path.join('configs', cls._confdir)
+        cls.createConfigDir(confdir)
+
+        cls.generateRecursorConfig(confdir)
+        cls.startRecursor(confdir, cls._recursorPort)
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.tearDownRecursor()
+
+    @classmethod
+    def generateRecursorConfig(cls, confdir):
+        super(testTooLargeToAddZeroScope, cls).generateRecursorConfig(confdir)
+
+    def testTooLarge(self):
+        qname = 'toolarge.ecs.'
+        ecso = clientsubnetoption.ClientSubnetOption('192.0.2.1', 24)
+        query = dns.message.make_query(qname, 'TXT', 'IN', use_edns=True, options=[ecso], payload=512)
+
+        # should not have an ECS Option since the packet is too large already
+        res = self.sendUDPQuery(query, timeout=5.0)
+        self.assertRcodeEqual(res, dns.rcode.NOERROR)
+        self.assertEqual(len(res.answer), 1)
+        self.assertEqual(res.edns, 0)
+        self.assertEqual(len(res.options), 0)
+
+        res = self.sendTCPQuery(query, timeout=5.0)
+        self.assertRcodeEqual(res, dns.rcode.NOERROR)
+        self.assertEqual(len(res.answer), 1)
+        self.assertEqual(res.edns, 0)
+        self.assertEqual(len(res.options), 1)
+        self.assertEqual(res.options[0].otype, 8)
+        self.assertEqual(res.options[0].scope, 0)
+
 class UDPECSResponder(DatagramProtocol):
     @staticmethod
     def ipToStr(option):
index fcc489b2bd2bee8bbee8b5d807ae1219a89b5eac..8200dcacdc6218a1b480c4d6a7c6eabf443105bd 100644 (file)
@@ -11,7 +11,6 @@ except NameError:
     pass
 
 from recursortests import RecursorTest
-from proxyprotocol import ProxyProtocol
 
 class ProxyProtocolRecursorTest(RecursorTest):
 
@@ -32,62 +31,6 @@ class ProxyProtocolRecursorTest(RecursorTest):
     def tearDownClass(cls):
         cls.tearDownRecursor()
 
-    @classmethod
-    def sendUDPQueryWithProxyProtocol(cls, query, v6, source, destination, sourcePort, destinationPort, values=[], timeout=2.0):
-        queryPayload = query.to_wire()
-        ppPayload = ProxyProtocol.getPayload(False, False, v6, source, destination, sourcePort, destinationPort, values)
-        payload = ppPayload + queryPayload
-
-        if timeout:
-            cls._sock.settimeout(timeout)
-
-        try:
-            cls._sock.send(payload)
-            data = cls._sock.recv(4096)
-        except socket.timeout:
-            data = None
-        finally:
-            if timeout:
-                cls._sock.settimeout(None)
-
-        message = None
-        if data:
-            message = dns.message.from_wire(data)
-        return message
-
-    @classmethod
-    def sendTCPQueryWithProxyProtocol(cls, query, v6, source, destination, sourcePort, destinationPort, values=[], timeout=2.0):
-        queryPayload = query.to_wire()
-        ppPayload = ProxyProtocol.getPayload(False, False, v6, source, destination, sourcePort, destinationPort, values)
-
-        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        if timeout:
-            sock.settimeout(timeout)
-
-        sock.connect(("127.0.0.1", cls._recursorPort))
-
-        try:
-            sock.send(ppPayload)
-            sock.send(struct.pack("!H", len(queryPayload)))
-            sock.send(queryPayload)
-            data = sock.recv(2)
-            if data:
-                (datalen,) = struct.unpack("!H", data)
-                data = sock.recv(datalen)
-        except socket.timeout as e:
-            print("Timeout: %s" % (str(e)))
-            data = None
-        except socket.error as e:
-            print("Network error: %s" % (str(e)))
-            data = None
-        finally:
-            sock.close()
-
-        message = None
-        if data:
-            message = dns.message.from_wire(data)
-        return message
-
 class ProxyProtocolAllowedRecursorTest(ProxyProtocolRecursorTest):
     _confdir = 'ProxyProtocol'
     _lua_dns_script_file = """