From: Charles-Henri Bruyand Date: Thu, 28 Dec 2023 17:54:13 +0000 (+0100) Subject: dnsdist: doq,doh3 make sure we enforce any ACL X-Git-Tag: auth-4.9.0-alpha1~16^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F13670%2Fhead;p=thirdparty%2Fpdns.git dnsdist: doq,doh3 make sure we enforce any ACL --- diff --git a/pdns/dnsdistdist/doh3.cc b/pdns/dnsdistdist/doh3.cc index a890e9375c..713e379f1b 100644 --- a/pdns/dnsdistdist/doh3.cc +++ b/pdns/dnsdistdist/doh3.cc @@ -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; diff --git a/pdns/dnsdistdist/doq.cc b/pdns/dnsdistdist/doq.cc index 6181ca769f..4431f6e4f0 100644 --- a/pdns/dnsdistdist/doq.cc +++ b/pdns/dnsdistdist/doq.cc @@ -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; diff --git a/regression-tests.dnsdist/quictests.py b/regression-tests.dnsdist/quictests.py index dfca492bb6..62cf24e757 100644 --- a/regression-tests.dnsdist/quictests.py +++ b/regression-tests.dnsdist/quictests.py @@ -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): """ diff --git a/regression-tests.dnsdist/test_DOH3.py b/regression-tests.dnsdist/test_DOH3.py index 4374bc2a9f..4704c26901 100644 --- a/regression-tests.dnsdist/test_DOH3.py +++ b/regression-tests.dnsdist/test_DOH3.py @@ -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' diff --git a/regression-tests.dnsdist/test_DOQ.py b/regression-tests.dnsdist/test_DOQ.py index 965e9d6dd3..69d61dc7a1 100644 --- a/regression-tests.dnsdist/test_DOQ.py +++ b/regression-tests.dnsdist/test_DOQ.py @@ -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)