From a139d6ddef76cabc203d0e9786110a6f3d3b3f2f Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Mon, 1 Sep 2025 12:22:55 +0200 Subject: [PATCH] dnsdist: Test that the configuration is correctly reloaded Signed-off-by: Remi Gacogne --- .../test_ConfigurationUpdates.py | 247 ++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 regression-tests.dnsdist/test_ConfigurationUpdates.py diff --git a/regression-tests.dnsdist/test_ConfigurationUpdates.py b/regression-tests.dnsdist/test_ConfigurationUpdates.py new file mode 100644 index 000000000..d0414cc0f --- /dev/null +++ b/regression-tests.dnsdist/test_ConfigurationUpdates.py @@ -0,0 +1,247 @@ +#!/usr/bin/env python +import base64 +import dns +import time +from dnsdisttests import DNSDistTest, pickAvailablePort +import extendederrors + +class TestConfigurationUpdates(DNSDistTest): + _yaml_config_template = """--- +console: + listen_address: "127.0.0.1:%d" + key: "%s" + acl: + - 127.0.0.0/8 + +binds: + - listen_address: "127.0.0.1:%d" + protocol: Do53 + - listen_address: "127.0.0.1:%d" + protocol: "DoT" + tls: + certificates: + - certificate: "%s" + key: "%s" + provider: "openssl" + - listen_address: "127.0.0.1:%d" + protocol: "DoH" + tls: + certificates: + - certificate: "%s" + key: "%s" + doh: + provider: "nghttp2" + paths: + - "/" + - listen_address: "127.0.0.1:%d" + protocol: "DoQ" + tls: + certificates: + - certificate: "%s" + key: "%s" + - listen_address: "127.0.0.1:%d" + protocol: "DoH3" + tls: + certificates: + - certificate: "%s" + key: "%s" + +backends: + - address: "127.0.0.1:%d" + protocol: Do53 + - address: "127.0.0.1:%d" + protocol: Do53 + tcp_only: true + pools: + - "tcp-pool" + +query_rules: + - name: "route TCP response test to the TCP-only pool" + selector: + type: "QName" + qname: "TCP-response.config-updates.test.powerdns.com." + action: + type: "Pool" + pool_name: "tcp-pool" +""" + _dnsDistPort = pickAvailablePort() + _tlsServerPort = pickAvailablePort() + _dohWithNGHTTP2ServerPort = pickAvailablePort() + _doqServerPort = pickAvailablePort() + _doh3ServerPort = pickAvailablePort() + _serverKey = 'server.key' + _serverCert = 'server.chain' + _serverName = 'tls.tests.dnsdist.org' + _dohWithNGHTTP2BaseURL = ("https://%s:%d/" % (_serverName, _dohWithNGHTTP2ServerPort)) + _dohBaseURL = ("https://%s:%d/" % (_serverName, _doh3ServerPort)) + _caCert = 'ca.pem' + _consoleKey = DNSDistTest.generateConsoleKey() + _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii') + _consolePort = pickAvailablePort() + _testServerPort = pickAvailablePort() + _yaml_config_params = ['_consolePort', '_consoleKeyB64', '_dnsDistPort', '_tlsServerPort', '_serverCert', '_serverKey', '_dohWithNGHTTP2ServerPort', '_serverCert', '_serverKey', '_doqServerPort','_serverCert', '_serverKey', '_doh3ServerPort', '_serverCert', '_serverKey', '_testServerPort', '_testServerPort'] + _config_params = [] + _checkConfigExpectedOutput = b"DNS over HTTPS configured\nConfiguration 'configs/dnsdist_TestConfigurationUpdates.yml' OK!\n" + + def testRegular(self): + """ + Configuration updates: regular + """ + for protocol in ['UDP', 'TCP', 'DOT', 'DOH', 'DOQ', 'DOH3']: + name = f'regular-{protocol}.config-updates.test.powerdns.com.' + query = dns.message.make_query(name, 'A', 'IN') + query.flags &= ~dns.flags.RD + response = dns.message.make_response(query) + rrset = dns.rrset.from_text(name, + 60, + dns.rdataclass.IN, + dns.rdatatype.A, + '127.0.0.1') + + response.answer.append(rrset) + + method = f'send{protocol}Query' + if not protocol in ['UDP', 'TCP']: + if protocol == 'DOH': + method = 'sendDOHWithNGHTTP2QueryWrapper' + else: + method += 'Wrapper' + sender = getattr(self, method) + + (receivedQuery, receivedResponse) = sender(query, response=response) + receivedQuery.id = query.id + self.assertEqual(receivedQuery, query) + self.assertEqual(receivedResponse, response) + + self.sendConsoleCommand(f'addAction(QNameRule("{name}"), RCodeAction(DNSRCode.REFUSED))') + + # the configuration should have been updated + response = dns.message.make_response(query) + response.set_rcode(dns.rcode.REFUSED) + (_, receivedResponse) = sender(query, response=None, useQueue=False) + self.assertEqual(receivedResponse, response) + + def testResponseRule(self): + """ + Configuration updates: response + """ + for protocol in ['UDP', 'TCP']: + name = f'{protocol}-response.config-updates.test.powerdns.com.' + query = dns.message.make_query(name, 'A', 'IN') + query.flags &= ~dns.flags.RD + response = dns.message.make_response(query) + rrset = dns.rrset.from_text(name, + 60, + dns.rdataclass.IN, + dns.rdatatype.A, + '127.0.0.1') + + response.answer.append(rrset) + + method = f'send{protocol}Query' + sender = getattr(self, method) + + (receivedQuery, receivedResponse) = sender(query, response=response) + receivedQuery.id = query.id + self.assertEqual(receivedQuery, query) + self.assertEqual(receivedResponse, response) + + self.sendConsoleCommand(f'addResponseAction(QNameRule("{name}"), SetExtendedDNSErrorResponseAction(15))') + if protocol == 'TCP': + time.sleep(1) + + # the configuration should have been updated + expectedResponse = dns.message.make_response(query) + ede = extendederrors.ExtendedErrorOption(15, b'') + expectedResponse.use_edns(edns=True, payload=4096, options=[ede]) + expectedResponse.answer.append(rrset) + (_, receivedResponse) = sender(query, response=response) + self.assertEqual(receivedResponse, expectedResponse) + +class TestConfigurationUpdatesRecvMMSG(DNSDistTest): + _yaml_config_template = """--- +console: + listen_address: "127.0.0.1:%d" + key: "%s" + acl: + - 127.0.0.0/8 + +binds: + - listen_address: "127.0.0.1:%d" + protocol: Do53 + +backends: + - address: "127.0.0.1:%d" + protocol: Do53 + +tuning: + udp: + messages_per_round: 10 +""" + _dnsDistPort = pickAvailablePort() + _consoleKey = DNSDistTest.generateConsoleKey() + _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii') + _consolePort = pickAvailablePort() + _testServerPort = pickAvailablePort() + _yaml_config_params = ['_consolePort', '_consoleKeyB64', '_dnsDistPort', '_testServerPort'] + _config_params = [] + + def testRecvMMSGUDP(self): + """ + Configuration updates: recvmmsg UDP + """ + name = 'recvmmsg-udp.config-updates.test.powerdns.com.' + query = dns.message.make_query(name, 'A', 'IN') + query.flags &= ~dns.flags.RD + response = dns.message.make_response(query) + rrset = dns.rrset.from_text(name, + 60, + dns.rdataclass.IN, + dns.rdatatype.A, + '127.0.0.1') + + response.answer.append(rrset) + + (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response=response) + receivedQuery.id = query.id + self.assertEqual(receivedQuery, query) + self.assertEqual(receivedResponse, response) + + self.sendConsoleCommand(f'addAction(QNameRule("{name}"), RCodeAction(DNSRCode.REFUSED))') + + # the configuration should have been updated + response = dns.message.make_response(query) + response.set_rcode(dns.rcode.REFUSED) + (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) + self.assertEqual(receivedResponse, response) + + def testUDPResponseRule(self): + """ + Configuration updates: UDP response + """ + name = 'recvmmsg-udp-response.config-updates.test.powerdns.com.' + query = dns.message.make_query(name, 'A', 'IN') + query.flags &= ~dns.flags.RD + response = dns.message.make_response(query) + rrset = dns.rrset.from_text(name, + 60, + dns.rdataclass.IN, + dns.rdatatype.A, + '127.0.0.1') + + response.answer.append(rrset) + + (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response=response) + receivedQuery.id = query.id + self.assertEqual(receivedQuery, query) + self.assertEqual(receivedResponse, response) + + self.sendConsoleCommand(f'addResponseAction(QNameRule("{name}"), SetExtendedDNSErrorResponseAction(15))') + + # the configuration should have been updated + expectedResponse = dns.message.make_response(query) + ede = extendederrors.ExtendedErrorOption(15, b'') + expectedResponse.use_edns(edns=True, payload=4096, options=[ede]) + expectedResponse.answer.append(rrset) + (_, receivedResponse) = self.sendUDPQuery(query, response=response) + self.assertEqual(receivedResponse, expectedResponse) -- 2.47.3