From eb76729d63245e2e8f06f4d6d52d2fd4aab4fb1f Mon Sep 17 00:00:00 2001 From: khramshinr Date: Tue, 30 Jan 2024 14:12:01 +0700 Subject: dns forwarding: T5687: Implement ECS settings for PowerDNS recursor --- data/templates/dns-forwarding/recursor.conf.j2 | 14 +++++++ .../service_dns_forwarding.xml.in | 43 +++++++++++++++++++ .../scripts/cli/test_service_dns_forwarding.py | 48 ++++++++++++++++++++++ 3 files changed, 105 insertions(+) diff --git a/data/templates/dns-forwarding/recursor.conf.j2 b/data/templates/dns-forwarding/recursor.conf.j2 index e4e8e7044..5ac872f19 100644 --- a/data/templates/dns-forwarding/recursor.conf.j2 +++ b/data/templates/dns-forwarding/recursor.conf.j2 @@ -57,3 +57,17 @@ serve-rfc1918={{ 'no' if no_serve_rfc1918 is vyos_defined else 'yes' }} auth-zones={% for z in authoritative_zones %}{{ z.name }}={{ z.file }}{{- "," if not loop.last -}}{% endfor %} forward-zones-file={{ config_dir }}/recursor.forward-zones.conf + +#ecs +{% if options.ecs_add_for is vyos_defined %} +ecs-add-for={{ options.ecs_add_for | join(',') }} +{% endif %} + +{% if options.ecs_ipv4_bits is vyos_defined %} +ecs-ipv4-bits={{ options.ecs_ipv4_bits }} +{% endif %} + +{% if options.edns_subnet_allow_list is vyos_defined %} +edns-subnet-allow-list={{ options.edns_subnet_allow_list | join(',') }} +{% endif %} + diff --git a/interface-definitions/service_dns_forwarding.xml.in b/interface-definitions/service_dns_forwarding.xml.in index 0f8863438..b520af44d 100644 --- a/interface-definitions/service_dns_forwarding.xml.in +++ b/interface-definitions/service_dns_forwarding.xml.in @@ -735,6 +735,49 @@ + + + DNS server options + + + + + List of client netmasks for which EDNS Client Subnet will be added + + ipv4net + IP addresses or subnets, negation supported + + + ipv6net + IPv6 addresses or subnets, negation supported + + + + + + + Number of bits of IPv4 address to pass for EDNS Client Subnet + + u32:0-32 + Number of bits of IPv4 address + + + + + + + + + List of netmasks and domains that we should enable EDNS subnet for + + txt + Netmask or domain + + + + + + diff --git a/smoketest/scripts/cli/test_service_dns_forwarding.py b/smoketest/scripts/cli/test_service_dns_forwarding.py index 652c4fa7b..2a32fa292 100755 --- a/smoketest/scripts/cli/test_service_dns_forwarding.py +++ b/smoketest/scripts/cli/test_service_dns_forwarding.py @@ -59,6 +59,12 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase): # Check for running process self.assertFalse(process_named_running(PROCESS_NAME)) + def _set_required_options(self): + for network in allow_from: + self.cli_set(base_path + ['allow-from', network]) + for address in listen_adress: + self.cli_set(base_path + ['listen-address', address]) + def test_basic_forwarding(self): # Check basic DNS forwarding settings cache_size = '20' @@ -294,5 +300,47 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase): tmp = get_config_value('local-port') self.assertEqual(tmp, port) + def test_ecs_add_for(self): + self._set_required_options() + + options = ['0.0.0.0/0', '!10.0.0.0/8', 'fc00::/7', '!fe80::/10'] + for param in options: + self.cli_set(base_path + ['options', 'ecs-add-for', param]) + + # commit changes + self.cli_commit() + + # verify ecs_add_for configuration + tmp = get_config_value('ecs-add-for') + self.assertEqual(tmp, ','.join(options)) + + def test_ecs_ipv4_bits(self): + self._set_required_options() + + option_value = '24' + self.cli_set(base_path + ['options', 'ecs-ipv4-bits', option_value]) + + # commit changes + self.cli_commit() + + # verify ecs_ipv4_bits configuration + tmp = get_config_value('ecs-ipv4-bits') + self.assertEqual(tmp, option_value) + + def test_edns_subnet_allow_list(self): + self._set_required_options() + + options = ['192.0.2.1/32', 'example.com', 'fe80::/10'] + for param in options: + self.cli_set(base_path + ['options', 'edns-subnet-allow-list', param]) + + # commit changes + self.cli_commit() + + # verify edns_subnet_allow_list configuration + tmp = get_config_value('edns-subnet-allow-list') + self.assertEqual(tmp, ','.join(options)) + + if __name__ == '__main__': unittest.main(verbosity=2) -- cgit v1.2.3 From c4b6c156549ea03262793c78532c2456e8713b81 Mon Sep 17 00:00:00 2001 From: khramshinr Date: Wed, 31 Jan 2024 12:13:07 +0700 Subject: dns forwarding: T5687: Implement ECS settings for PowerDNS recursor Fix option descriptions --- interface-definitions/service_dns_forwarding.xml.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface-definitions/service_dns_forwarding.xml.in b/interface-definitions/service_dns_forwarding.xml.in index b520af44d..788f0c18e 100644 --- a/interface-definitions/service_dns_forwarding.xml.in +++ b/interface-definitions/service_dns_forwarding.xml.in @@ -742,7 +742,7 @@ - List of client netmasks for which EDNS Client Subnet will be added + Client netmask for which EDNS Client Subnet will be added ipv4net IP addresses or subnets, negation supported @@ -768,7 +768,7 @@ - List of netmasks and domains that we should enable EDNS subnet for + Netmask or domain that we should enable EDNS subnet for txt Netmask or domain -- cgit v1.2.3 From 049560725b93de49ec2d5a779e391e61d568ceb6 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Thu, 1 Feb 2024 20:32:04 +0100 Subject: dns forwarding: T5687: add missing constraints on ecs-add-for CLI node Completion help suggests only IPv4 and IPv6 prefixes are supported, thus add a proper constraint enforcing this. --- interface-definitions/service_dns_forwarding.xml.in | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/interface-definitions/service_dns_forwarding.xml.in b/interface-definitions/service_dns_forwarding.xml.in index 788f0c18e..a54618e82 100644 --- a/interface-definitions/service_dns_forwarding.xml.in +++ b/interface-definitions/service_dns_forwarding.xml.in @@ -745,12 +745,26 @@ Client netmask for which EDNS Client Subnet will be added ipv4net - IP addresses or subnets, negation supported + IPv4 prefix to match + + + !ipv4net + Match everything except the specified IPv4 prefix ipv6net - IPv6 addresses or subnets, negation supported + IPv6 prefix to match + + + !ipv6net + Match everything except the specified IPv6 prefix + + + + + + -- cgit v1.2.3 From 112376a4ccb96ceee647a4cba5c4f131597b0ea4 Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Thu, 1 Feb 2024 20:32:40 +0100 Subject: smoketest: T5687: simplify "dns forwarding" test setup Commit eb76729d6324 ("dns forwarding: T5687: Implement ECS settings for PowerDNS recursor") added a helper "_set_required_options()" method to reduce duplicate code when setting up the base interface test. This refactors the test class to call this code always in setUp() so we have it written only once. --- .../scripts/cli/test_service_dns_forwarding.py | 65 +++------------------- 1 file changed, 7 insertions(+), 58 deletions(-) diff --git a/smoketest/scripts/cli/test_service_dns_forwarding.py b/smoketest/scripts/cli/test_service_dns_forwarding.py index 2a32fa292..079c584ba 100755 --- a/smoketest/scripts/cli/test_service_dns_forwarding.py +++ b/smoketest/scripts/cli/test_service_dns_forwarding.py @@ -59,7 +59,9 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase): # Check for running process self.assertFalse(process_named_running(PROCESS_NAME)) - def _set_required_options(self): + def setUp(self): + # forward to base class + super().setUp() for network in allow_from: self.cli_set(base_path + ['allow-from', network]) for address in listen_adress: @@ -70,6 +72,10 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase): cache_size = '20' negative_ttl = '120' + # remove code from setUp() as in this test-case we validate the proper + # handling of assertions when specific CLI nodes are missing + self.cli_delete(base_path) + self.cli_set(base_path + ['cache-size', cache_size]) self.cli_set(base_path + ['negative-ttl', negative_ttl]) @@ -124,12 +130,6 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase): def test_dnssec(self): # DNSSEC option testing - - for network in allow_from: - self.cli_set(base_path + ['allow-from', network]) - for address in listen_adress: - self.cli_set(base_path + ['listen-address', address]) - options = ['off', 'process-no-validate', 'process', 'log-fail', 'validate'] for option in options: self.cli_set(base_path + ['dnssec', option]) @@ -142,12 +142,6 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase): def test_external_nameserver(self): # Externe Domain Name Servers (DNS) addresses - - for network in allow_from: - self.cli_set(base_path + ['allow-from', network]) - for address in listen_adress: - self.cli_set(base_path + ['listen-address', address]) - nameservers = {'192.0.2.1': {}, '192.0.2.2': {'port': '53'}, '2001:db8::1': {'port': '853'}} for h,p in nameservers.items(): if 'port' in p: @@ -169,11 +163,6 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase): self.assertEqual(tmp, 'yes') def test_domain_forwarding(self): - for network in allow_from: - self.cli_set(base_path + ['allow-from', network]) - for address in listen_adress: - self.cli_set(base_path + ['listen-address', address]) - domains = ['vyos.io', 'vyos.net', 'vyos.com'] nameservers = {'192.0.2.1': {}, '192.0.2.2': {'port': '53'}, '2001:db8::1': {'port': '853'}} for domain in domains: @@ -210,11 +199,6 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase): self.assertIn(f'addNTA("{domain}", "static")', hosts_conf) def test_no_rfc1918_forwarding(self): - for network in allow_from: - self.cli_set(base_path + ['allow-from', network]) - for address in listen_adress: - self.cli_set(base_path + ['listen-address', address]) - self.cli_set(base_path + ['no-serve-rfc1918']) # commit changes @@ -226,12 +210,6 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase): def test_dns64(self): dns_prefix = '64:ff9b::/96' - - for network in allow_from: - self.cli_set(base_path + ['allow-from', network]) - for address in listen_adress: - self.cli_set(base_path + ['listen-address', address]) - # Check dns64-prefix - must be prefix /96 self.cli_set(base_path + ['dns64-prefix', '2001:db8:aabb::/64']) with self.assertRaises(ConfigSessionError): @@ -252,12 +230,6 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase): '2001:db8:85a3:8d3:1319:8a2e:370:7348', '64:ff9b::/96' ] - - for network in allow_from: - self.cli_set(base_path + ['allow-from', network]) - for address in listen_adress: - self.cli_set(base_path + ['listen-address', address]) - for exclude_throttle_adress in exclude_throttle_adress_examples: self.cli_set(base_path + ['exclude-throttle-address', exclude_throttle_adress]) @@ -270,16 +242,9 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase): def test_serve_stale_extension(self): server_stale = '20' - for network in allow_from: - self.cli_set(base_path + ['allow-from', network]) - for address in listen_adress: - self.cli_set(base_path + ['listen-address', address]) - self.cli_set(base_path + ['serve-stale-extension', server_stale]) - # commit changes self.cli_commit() - # verify configuration tmp = get_config_value('serve-stale-extensions') self.assertEqual(tmp, server_stale) @@ -288,48 +253,33 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase): # We can listen on a different port compared to '53' but only one at a time for port in ['10053', '10054']: self.cli_set(base_path + ['port', port]) - for network in allow_from: - self.cli_set(base_path + ['allow-from', network]) - for address in listen_adress: - self.cli_set(base_path + ['listen-address', address]) - # commit changes self.cli_commit() - # verify local-port configuration tmp = get_config_value('local-port') self.assertEqual(tmp, port) def test_ecs_add_for(self): - self._set_required_options() - options = ['0.0.0.0/0', '!10.0.0.0/8', 'fc00::/7', '!fe80::/10'] for param in options: self.cli_set(base_path + ['options', 'ecs-add-for', param]) # commit changes self.cli_commit() - # verify ecs_add_for configuration tmp = get_config_value('ecs-add-for') self.assertEqual(tmp, ','.join(options)) def test_ecs_ipv4_bits(self): - self._set_required_options() - option_value = '24' self.cli_set(base_path + ['options', 'ecs-ipv4-bits', option_value]) - # commit changes self.cli_commit() - # verify ecs_ipv4_bits configuration tmp = get_config_value('ecs-ipv4-bits') self.assertEqual(tmp, option_value) def test_edns_subnet_allow_list(self): - self._set_required_options() - options = ['192.0.2.1/32', 'example.com', 'fe80::/10'] for param in options: self.cli_set(base_path + ['options', 'edns-subnet-allow-list', param]) @@ -341,6 +291,5 @@ class TestServicePowerDNS(VyOSUnitTestSHIM.TestCase): tmp = get_config_value('edns-subnet-allow-list') self.assertEqual(tmp, ','.join(options)) - if __name__ == '__main__': unittest.main(verbosity=2) -- cgit v1.2.3