]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: doq,doh3 make sure we enforce any ACL 13670/head
authorCharles-Henri Bruyand <charles-henri.bruyand@open-xchange.com>
Thu, 28 Dec 2023 17:54:13 +0000 (18:54 +0100)
committerCharles-Henri Bruyand <charles-henri.bruyand@open-xchange.com>
Thu, 28 Dec 2023 17:54:13 +0000 (18:54 +0100)
pdns/dnsdistdist/doh3.cc
pdns/dnsdistdist/doq.cc
regression-tests.dnsdist/quictests.py
regression-tests.dnsdist/test_DOH3.py
regression-tests.dnsdist/test_DOQ.py

index a890e9375c09f9649907c06ec4b0c72aa44bcd12..713e379f1b2cb34d2d0fb03c13e5ec6588dbbba9 100644 (file)
@@ -471,6 +471,16 @@ static void processDOH3Query(DOH3UnitUniquePtr&& doh3Unit)
     auto& holders = dsc->holders;
     ClientState& clientState = *dsc->clientState;
 
+    if (!holders.acl->match(remote)) {
+      vinfolog("Query from %s (DoH3) dropped because of ACL", remote.toStringWithPort());
+      ++dnsdist::metrics::g_stats.aclDrops;
+      unit->response.clear();
+
+      unit->status_code = 403;
+      handleImmediateResponse(std::move(unit), "DoH3 query dropped because of ACL");
+      return;
+    }
+
     if (unit->query.size() < sizeof(dnsheader)) {
       ++dnsdist::metrics::g_stats.nonCompliantQueries;
       ++clientState.nonCompliantQueries;
index 6181ca769f1469316d12f400753c6984ae5d21d3..4431f6e4f0ef391c201345e97cd77758cc5835c7 100644 (file)
@@ -400,6 +400,15 @@ static void processDOQQuery(DOQUnitUniquePtr&& doqUnit)
     auto& holders = dsc->holders;
     ClientState& clientState = *dsc->clientState;
 
+    if (!holders.acl->match(remote)) {
+      vinfolog("Query from %s (DoQ) dropped because of ACL", remote.toStringWithPort());
+      ++dnsdist::metrics::g_stats.aclDrops;
+      unit->response.clear();
+
+      handleImmediateResponse(std::move(unit), "DoQ query dropped because of ACL");
+      return;
+    }
+
     if (unit->query.size() < sizeof(dnsheader)) {
       ++dnsdist::metrics::g_stats.nonCompliantQueries;
       ++clientState.nonCompliantQueries;
index dfca492bb6a14a8eeda170e1585a14c7c1e632aa..62cf24e757a47bfa63149d5c1352d0e6b9fa4a2f 100644 (file)
@@ -118,6 +118,23 @@ class QUICTests(object):
         except StreamResetError as e :
             self.assertEqual(e.error, 5);
 
+class QUICACLTests(object):
+
+    def testDropped(self):
+        """
+        QUIC: Dropped query because of ACL
+        """
+        name = 'acl.doq.tests.powerdns.com.'
+        query = dns.message.make_query(name, 'A', 'IN')
+        dropped = False
+        try:
+            (_, receivedResponse) = self.sendQUICQuery(query, response=None, useQueue=False)
+            self.assertTrue(False)
+        except StreamResetError as e:
+            self.assertEqual(e.error, 5);
+            dropped = True
+        self.assertTrue(dropped)
+
 class QUICWithCacheTests(object):
     def testCached(self):
         """
index 4374bc2a9f4365f6e6b77e03d89530695f7320aa..4704c26901e292afffb2fddb6536f03e8eb0bd8f 100644 (file)
@@ -4,7 +4,7 @@ import clientsubnetoption
 
 from dnsdisttests import DNSDistTest
 from dnsdisttests import pickAvailablePort
-from quictests import QUICTests, QUICWithCacheTests
+from quictests import QUICTests, QUICWithCacheTests, QUICACLTests
 import doh3client
 
 class TestDOH3(QUICTests, DNSDistTest):
@@ -33,6 +33,28 @@ class TestDOH3(QUICTests, DNSDistTest):
     def sendQUICQuery(self, query, response=None, useQueue=True, connection=None):
         return self.sendDOH3Query(self._doqServerPort, self._dohBaseURL, query, response=response, caFile=self._caCert, useQueue=useQueue, serverName=self._serverName, connection=connection)
 
+class TestDOH3ACL(QUICACLTests, DNSDistTest):
+    _serverKey = 'server.key'
+    _serverCert = 'server.chain'
+    _serverName = 'tls.tests.dnsdist.org'
+    _caCert = 'ca.pem'
+    _doqServerPort = pickAvailablePort()
+    _dohBaseURL = ("https://%s:%d/" % (_serverName, _doqServerPort))
+    _config_template = """
+    newServer{address="127.0.0.1:%d"}
+
+    setACL("192.0.2.1/32")
+    addDOH3Local("127.0.0.1:%d", "%s", "%s", {keyLogFile='/tmp/keys'})
+    """
+    _config_params = ['_testServerPort', '_doqServerPort','_serverCert', '_serverKey']
+    _verboseMode = True
+
+    def getQUICConnection(self):
+        return self.getDOQConnection(self._doqServerPort, self._caCert)
+
+    def sendQUICQuery(self, query, response=None, useQueue=True, connection=None):
+        return self.sendDOH3Query(self._doqServerPort, self._dohBaseURL, query, response=response, caFile=self._caCert, useQueue=useQueue, serverName=self._serverName, connection=connection)
+
 class TestDOH3Specifics(DNSDistTest):
     _serverKey = 'server.key'
     _serverCert = 'server.chain'
index 965e9d6dd32ae15f5061a1b857aa2f550a75dd87..69d61dc7a1d39e1bdc9769780ea1540394d94337 100644 (file)
@@ -5,7 +5,7 @@ import clientsubnetoption
 from dnsdisttests import DNSDistTest
 from dnsdisttests import pickAvailablePort
 from doqclient import quic_bogus_query
-from quictests import QUICTests, QUICWithCacheTests
+from quictests import QUICTests, QUICWithCacheTests, QUICACLTests
 import doqclient
 
 class TestDOQBogus(DNSDistTest):
@@ -85,3 +85,24 @@ class TestDOQWithCache(QUICWithCacheTests, DNSDistTest):
 
     def sendQUICQuery(self, query, response=None, useQueue=True, connection=None):
         return self.sendDOQQuery(self._doqServerPort, query, response=response, caFile=self._caCert, useQueue=useQueue, serverName=self._serverName, connection=connection)
+
+class TestDOQWithACL(QUICACLTests, DNSDistTest):
+    _serverKey = 'server.key'
+    _serverCert = 'server.chain'
+    _serverName = 'tls.tests.dnsdist.org'
+    _caCert = 'ca.pem'
+    _doqServerPort = pickAvailablePort()
+    _config_template = """
+    newServer{address="127.0.0.1:%d"}
+
+    setACL("192.0.2.1/32")
+    addDOQLocal("127.0.0.1:%d", "%s", "%s")
+    """
+    _config_params = ['_testServerPort', '_doqServerPort','_serverCert', '_serverKey']
+    _verboseMode = True
+
+    def getQUICConnection(self):
+        return self.getDOQConnection(self._doqServerPort, self._caCert)
+
+    def sendQUICQuery(self, query, response=None, useQueue=True, connection=None):
+        return self.sendDOQQuery(self._doqServerPort, query, response=response, caFile=self._caCert, useQueue=useQueue, serverName=self._serverName, connection=connection)