diff --git a/bin/tests/system/dnstap/tests_dnstap.py b/bin/tests/system/dnstap/tests_dnstap.py index 87533f4214..e27ad9d373 100644 --- a/bin/tests/system/dnstap/tests_dnstap.py +++ b/bin/tests/system/dnstap/tests_dnstap.py @@ -41,7 +41,7 @@ def test_dnstap_dispatch_socket_addresses(named_port): resolver.port = named_port # Send some query to ns3 so that it records something in its dnstap file. - ans = resolver.query("mail.example.", "A") + ans = resolver.resolve("mail.example.", "A") assert ans[0].address == "10.0.0.2" # Before continuing, roll dnstap file to ensure it is flushed to disk. diff --git a/bin/tests/system/rpzextra/clean.sh b/bin/tests/system/rpzextra/clean.sh index def4d72678..928ee8ba87 100644 --- a/bin/tests/system/rpzextra/clean.sh +++ b/bin/tests/system/rpzextra/clean.sh @@ -18,3 +18,4 @@ rm -f ns*/named.memstats rm -f ns*/named.run rm -f ns*/rpz*.txt rm -rf __pycache__ +rm -f ns3/*-rpz-external.local.db diff --git a/bin/tests/system/rpzextra/ns1/named.conf.in b/bin/tests/system/rpzextra/ns1/named.conf.in deleted file mode 100644 index 202ffa7006..0000000000 --- a/bin/tests/system/rpzextra/ns1/named.conf.in +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) Internet Systems Consortium, Inc. ("ISC") - * - * SPDX-License-Identifier: MPL-2.0 - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * See the COPYRIGHT file distributed with this work for additional - * information regarding copyright ownership. - */ - -key rndc_key { - secret "1234abcd8765"; - algorithm @DEFAULT_HMAC@; -}; - -controls { - inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; -}; - -options { - query-source address 10.53.0.1; - notify-source 10.53.0.1; - transfer-source 10.53.0.1; - port @PORT@; - listen-on { 10.53.0.1; }; - pid-file "named.pid"; - notify no; - dnssec-validation no; - allow-query { any; }; - recursion yes; - allow-recursion { any; }; - - response-policy { - zone "rpz.local"; - }; -}; - -logging { - channel rpz_passthru { - file "rpz_passthru.txt" versions 3 size 5m; - print-time yes; - print-category yes; - print-severity yes; - severity info; - }; - - channel rpz_log { - file "rpz.txt" versions 3 size 20m; - print-time yes; - print-category yes; - print-severity yes; - severity info; - }; - - category rpz { rpz_log; default_debug; }; - category rpz-passthru { rpz_passthru; default_debug; }; -}; - -zone "rpz.local" { - type primary; - file "rpz.local.db"; - allow-transfer { none; }; - allow-query { localhost; }; -}; - -zone "." { - type hint; - file "root.db"; -}; - - diff --git a/bin/tests/system/rpzextra/ns2/gooddomain.db b/bin/tests/system/rpzextra/ns2/gooddomain.db new file mode 100644 index 0000000000..1fb720cc7b --- /dev/null +++ b/bin/tests/system/rpzextra/ns2/gooddomain.db @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 + +@ IN SOA ns1 root.gooddomain. ( + 2020040101 + 4h + 1h + 1w + 60 +) + + IN NS ns1 + +ns1 IN A 10.53.0.2 + +gooddomain. IN A 10.53.0.2 +www IN A 10.53.0.3 diff --git a/bin/tests/system/rpzextra/ns2/named.conf.in b/bin/tests/system/rpzextra/ns2/named.conf.in index 17295efc01..6317563dc9 100644 --- a/bin/tests/system/rpzextra/ns2/named.conf.in +++ b/bin/tests/system/rpzextra/ns2/named.conf.in @@ -44,3 +44,14 @@ zone "baddomain" { allow-transfer { none; }; }; +zone "gooddomain" { + type primary; + file "gooddomain.db"; + allow-transfer { none; }; +}; + +zone "rpz-external.local" { + type primary; + file "rpz-external.local.db"; + allow-transfer { any; }; +}; diff --git a/bin/tests/system/rpzextra/ns2/rpz-external.local.db b/bin/tests/system/rpzextra/ns2/rpz-external.local.db new file mode 100644 index 0000000000..b3ab69ee6d --- /dev/null +++ b/bin/tests/system/rpzextra/ns2/rpz-external.local.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 + +@ IN SOA localhost.rpz-external.local root.rpz-external.local. ( + 2020022500 ; serial number + 60 ; refresh every minute + 60 ; retry every minute + 432000 ; expire in 5 days + 60 ; negative caching ttl, 1 minute +) + + + IN NS LOCALHOST. + +allowed IN CNAME . +*.allowed IN CNAME . diff --git a/bin/tests/system/rpzextra/ns3/external-rpz.local.db b/bin/tests/system/rpzextra/ns3/external-rpz.local.db new file mode 100644 index 0000000000..aad6b89dc6 --- /dev/null +++ b/bin/tests/system/rpzextra/ns3/external-rpz.local.db @@ -0,0 +1,29 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 + +@ IN SOA localhost.rpz.local root.rpz.local. ( + 2020022500 ; serial number + 60 ; refresh every minute + 60 ; retry every minute + 432000 ; expire in 5 days + 60 ; negative caching ttl, 1 minute +) + + + IN NS LOCALHOST. + +allowed IN CNAME rpz-passthru. +*.allowed IN CNAME rpz-passthru. + +gooddomain IN CNAME . +*.gooddomain IN CNAME . diff --git a/bin/tests/system/rpzextra/ns1/rpz.local.db b/bin/tests/system/rpzextra/ns3/first-rpz.local.db similarity index 100% rename from bin/tests/system/rpzextra/ns1/rpz.local.db rename to bin/tests/system/rpzextra/ns3/first-rpz.local.db diff --git a/bin/tests/system/rpzextra/ns3/fourth-rpz-extra.local.db b/bin/tests/system/rpzextra/ns3/fourth-rpz-extra.local.db new file mode 100644 index 0000000000..471030c3d9 --- /dev/null +++ b/bin/tests/system/rpzextra/ns3/fourth-rpz-extra.local.db @@ -0,0 +1,32 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 + +@ IN SOA localhost.rpz-extra.local root.rpz-extra.local. ( + 2020022500 ; serial number + 60 ; refresh every minute + 60 ; retry every minute + 432000 ; expire in 5 days + 60 ; negative caching ttl, 1 minute +) + + + IN NS LOCALHOST. + +allowed IN CNAME rpz-passthru. +*.allowed IN CNAME rpz-passthru. + +gooddomain IN CNAME . +*.gooddomain IN CNAME . + +baddomain IN CNAME . +*.baddomain IN CNAME . diff --git a/bin/tests/system/rpzextra/ns1/named.args b/bin/tests/system/rpzextra/ns3/named.args similarity index 100% rename from bin/tests/system/rpzextra/ns1/named.args rename to bin/tests/system/rpzextra/ns3/named.args diff --git a/bin/tests/system/rpzextra/ns3/named.conf.in b/bin/tests/system/rpzextra/ns3/named.conf.in new file mode 100644 index 0000000000..cd459bcda6 --- /dev/null +++ b/bin/tests/system/rpzextra/ns3/named.conf.in @@ -0,0 +1,147 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + listen-on { 10.53.0.3; }; + pid-file "named.pid"; + notify no; + dnssec-validation no; + allow-query { any; }; + recursion yes; + allow-recursion { any; }; + empty-zones-enable false; + response-policy { + zone "rpz-extra.local"; + }; +}; + +logging { + channel rpz_passthru { + file "rpz_passthru.txt" versions 3 size 5m; + print-time yes; + print-category yes; + print-severity yes; + severity info; + }; + + channel rpz_log { + file "rpz.txt" versions 3 size 20m; + print-time yes; + print-category yes; + print-severity yes; + severity info; + }; + + category rpz { rpz_log; default_debug; }; + category rpz-passthru { rpz_passthru; default_debug; }; +}; + +view "first" { + match-clients { 10.53.0.1; }; + zone "." { + type hint; + file "root.db"; + }; + zone "rpz.local" { + type primary; + file "first-rpz.local.db"; + allow-transfer { none; }; + allow-query { localhost; }; + }; + response-policy { + zone "rpz.local"; + }; +}; + +view "second" { + match-clients { 10.53.0.2; }; + zone "." { + type hint; + file "root.db"; + }; + zone "rpz-external.local" { + type secondary; + primaries { 10.53.0.2; }; + file "second-rpz-external.local.db"; + allow-query { 10.53.0.2; }; + }; + response-policy { + zone "rpz-external.local"; + }; +}; + +view "third" { + match-clients { 10.53.0.3; }; + zone "." { + type hint; + file "root.db"; + }; + zone "rpz-extra.local" { + type primary; + file "third-rpz-extra.local.db"; + allow-transfer { none; }; + allow-query { localhost; }; + }; +}; + +view "fourth" { + match-clients { 10.53.0.4; }; + zone "." { + type hint; + file "root.db"; + }; + zone "rpz-extra.local" { + type primary; + file "fourth-rpz-extra.local.db"; + allow-transfer { none; }; + allow-query { localhost; }; + }; +}; + +view "external" { + match-clients { any; }; + zone "." { + type hint; + file "root.db"; + }; + zone "rpz.local" { + type primary; + file "external-rpz.local.db"; + allow-transfer { none; }; + allow-query { localhost; }; + }; + zone "rpz-external.local" { + type secondary; + masterfile-format text; + primaries { 10.53.0.2; }; + file "external-rpz-external.local.db"; + allow-query { 10.53.0.5; }; + }; + response-policy { + zone "rpz-external.local"; + zone "rpz.local"; + }; +}; diff --git a/bin/tests/system/rpzextra/ns1/root.db b/bin/tests/system/rpzextra/ns3/root.db similarity index 92% rename from bin/tests/system/rpzextra/ns1/root.db rename to bin/tests/system/rpzextra/ns3/root.db index dde42dfe7e..ca499888b1 100644 --- a/bin/tests/system/rpzextra/ns1/root.db +++ b/bin/tests/system/rpzextra/ns3/root.db @@ -25,3 +25,6 @@ ns1.allowed. A 10.53.0.2 baddomain. NS ns1.baddomain. ns1.baddomain. A 10.53.0.2 + +gooddomain. NS ns1.gooddomain. +ns1.gooddomain. A 10.53.0.2 diff --git a/bin/tests/system/rpzextra/ns3/third-rpz-extra.local.db b/bin/tests/system/rpzextra/ns3/third-rpz-extra.local.db new file mode 100644 index 0000000000..a8b46faac1 --- /dev/null +++ b/bin/tests/system/rpzextra/ns3/third-rpz-extra.local.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 + +@ IN SOA localhost.rpz-extra.local root.rpz-extra.local. ( + 2020022500 ; serial number + 60 ; refresh every minute + 60 ; retry every minute + 432000 ; expire in 5 days + 60 ; negative caching ttl, 1 minute +) + + + IN NS LOCALHOST. + +allowed IN CNAME rpz-passthru. +*.allowed IN CNAME rpz-passthru. diff --git a/bin/tests/system/rpzextra/setup.sh b/bin/tests/system/rpzextra/setup.sh index 28a4719e70..2dbb388f72 100644 --- a/bin/tests/system/rpzextra/setup.sh +++ b/bin/tests/system/rpzextra/setup.sh @@ -17,5 +17,5 @@ set -e . ../conf.sh -copy_setports ns1/named.conf.in ns1/named.conf copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf diff --git a/bin/tests/system/rpzextra/tests_rpz_passthru_logging.py b/bin/tests/system/rpzextra/tests_rpz_passthru_logging.py deleted file mode 100755 index 326284739e..0000000000 --- a/bin/tests/system/rpzextra/tests_rpz_passthru_logging.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/python3 - -# Copyright (C) Internet Systems Consortium, Inc. ("ISC") -# -# SPDX-License-Identifier: MPL-2.0 -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, you can obtain one at https://mozilla.org/MPL/2.0/. -# -# See the COPYRIGHT file distributed with this work for additional -# information regarding copyright ownership. - -import os - -import pytest - -pytest.importorskip("dns") -import dns.resolver - - -def test_rpz_passthru_logging(named_port): - resolver = dns.resolver.Resolver() - resolver.nameservers = ["10.53.0.1"] - resolver.port = named_port - - # Should generate a log entry into rpz_passthru.txt - ans = resolver.query("allowed.", "A") - for rd in ans: - assert rd.address == "10.53.0.2" - - # baddomain.com isn't allowed (CNAME .), should return NXDOMAIN - # Should generate a log entry into rpz.txt - with pytest.raises(dns.resolver.NXDOMAIN): - resolver.query("baddomain.", "A") - - rpz_passthru_logfile = os.path.join("ns1", "rpz_passthru.txt") - rpz_logfile = os.path.join("ns1", "rpz.txt") - - assert os.path.isfile(rpz_passthru_logfile) - assert os.path.isfile(rpz_logfile) - - with open(rpz_passthru_logfile, encoding="utf-8") as log_file: - line = log_file.read() - assert "rpz QNAME PASSTHRU rewrite allowed/A/IN" in line - - with open(rpz_logfile, encoding="utf-8") as log_file: - line = log_file.read() - assert "rpz QNAME PASSTHRU rewrite allowed/A/IN" not in line - assert "rpz QNAME NXDOMAIN rewrite baddomain/A/IN" in line diff --git a/bin/tests/system/rpzextra/tests_rpzextra.py b/bin/tests/system/rpzextra/tests_rpzextra.py new file mode 100644 index 0000000000..ab5da45973 --- /dev/null +++ b/bin/tests/system/rpzextra/tests_rpzextra.py @@ -0,0 +1,143 @@ +#!/usr/bin/python3 + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import time +import os + +import pytest + +pytest.importorskip("dns", minversion="2.0.0") +import dns.resolver + + +def wait_for_transfer(ip, port, client_ip, name, rrtype): + resolver = dns.resolver.Resolver() + resolver.nameservers = [ip] + resolver.port = port + + for _ in range(10): + try: + resolver.resolve(name, rrtype, source=client_ip) + except dns.resolver.NoNameservers: + time.sleep(1) + else: + break + else: + raise RuntimeError( + "zone transfer failed: " + f"client {client_ip} got NXDOMAIN for {name} {rrtype} from @{ip}:{port}" + ) + + +def test_rpz_multiple_views(named_port): + resolver = dns.resolver.Resolver() + resolver.nameservers = ["10.53.0.3"] + resolver.port = named_port + + wait_for_transfer("10.53.0.3", named_port, "10.53.0.2", "rpz-external.local", "SOA") + wait_for_transfer("10.53.0.3", named_port, "10.53.0.5", "rpz-external.local", "SOA") + + # For 10.53.0.1 source IP: + # - baddomain.com isn't allowed (CNAME .), should return NXDOMAIN + # - gooddomain.com is allowed + # - allowed. is allowed + with pytest.raises(dns.resolver.NXDOMAIN): + resolver.resolve("baddomain.", "A", source="10.53.0.1") + + ans = resolver.resolve("gooddomain.", "A", source="10.53.0.1") + assert ans[0].address == "10.53.0.2" + + ans = resolver.resolve("allowed.", "A", source="10.53.0.1") + assert ans[0].address == "10.53.0.2" + + # For 10.53.0.2 source IP: + # - allowed.com isn't allowed (CNAME .), should return NXDOMAIN + # - baddomain.com is allowed + # - gooddomain.com is allowed + ans = resolver.resolve("baddomain.", "A", source="10.53.0.2") + assert ans[0].address == "10.53.0.2" + + ans = resolver.resolve("gooddomain.", "A", source="10.53.0.2") + assert ans[0].address == "10.53.0.2" + + with pytest.raises(dns.resolver.NXDOMAIN): + resolver.resolve("allowed.", "A", source="10.53.0.2") + + # For 10.53.0.3 source IP: + # - gooddomain.com is allowed + # - baddomain.com is allowed + # - allowed. is allowed + ans = resolver.resolve("baddomain.", "A", source="10.53.0.3") + assert ans[0].address == "10.53.0.2" + + ans = resolver.resolve("gooddomain.", "A", source="10.53.0.3") + assert ans[0].address == "10.53.0.2" + + ans = resolver.resolve("allowed.", "A", source="10.53.0.3") + assert ans[0].address == "10.53.0.2" + + # For 10.53.0.4 source IP: + # - gooddomain.com isn't allowed (CNAME .), should return NXDOMAIN + # - baddomain.com isn't allowed (CNAME .), should return NXDOMAIN + # - allowed. is allowed + with pytest.raises(dns.resolver.NXDOMAIN): + resolver.resolve("baddomain.", "A", source="10.53.0.4") + + with pytest.raises(dns.resolver.NXDOMAIN): + resolver.resolve("gooddomain.", "A", source="10.53.0.4") + + ans = resolver.resolve("allowed.", "A", source="10.53.0.4") + assert ans[0].address == "10.53.0.2" + + # For 10.53.0.5 (any) source IP: + # - baddomain.com is allowed + # - gooddomain.com isn't allowed (CNAME .), should return NXDOMAIN + # - allowed.com isn't allowed (CNAME .), should return NXDOMAIN + ans = resolver.resolve("baddomain.", "A", source="10.53.0.5") + assert ans[0].address == "10.53.0.2" + + with pytest.raises(dns.resolver.NXDOMAIN): + resolver.resolve("gooddomain.", "A", source="10.53.0.5") + + with pytest.raises(dns.resolver.NXDOMAIN): + resolver.resolve("allowed.", "A", source="10.53.0.5") + + +def test_rpz_passthru_logging(named_port): + resolver = dns.resolver.Resolver() + resolver.nameservers = ["10.53.0.3"] + resolver.port = named_port + + # Should generate a log entry into rpz_passthru.txt + ans = resolver.resolve("allowed.", "A", source="10.53.0.1") + assert ans[0].address == "10.53.0.2" + + # baddomain.com isn't allowed (CNAME .), should return NXDOMAIN + # Should generate a log entry into rpz.txt + with pytest.raises(dns.resolver.NXDOMAIN): + resolver.resolve("baddomain.", "A", source="10.53.0.1") + + rpz_passthru_logfile = os.path.join("ns3", "rpz_passthru.txt") + rpz_logfile = os.path.join("ns3", "rpz.txt") + + assert os.path.isfile(rpz_passthru_logfile) + assert os.path.isfile(rpz_logfile) + + with open(rpz_passthru_logfile, encoding="utf-8") as log_file: + line = log_file.read() + assert "rpz QNAME PASSTHRU rewrite allowed/A/IN" in line + + with open(rpz_logfile, encoding="utf-8") as log_file: + line = log_file.read() + assert "rpz QNAME PASSTHRU rewrite allowed/A/IN" not in line + assert "rpz QNAME NXDOMAIN rewrite baddomain/A/IN" in line diff --git a/bin/tests/system/shutdown/tests_shutdown.py b/bin/tests/system/shutdown/tests_shutdown.py index 46c2d509b1..aff69c5e3a 100755 --- a/bin/tests/system/shutdown/tests_shutdown.py +++ b/bin/tests/system/shutdown/tests_shutdown.py @@ -169,7 +169,7 @@ def test_named_shutdown(named_port, control_port): # wait for named to finish loading for _ in range(10): try: - resolver.query("version.bind", "TXT", "CH") + resolver.resolve("version.bind", "TXT", "CH") break except (dns.resolver.NoNameservers, dns.exception.Timeout): time.sleep(1)