From 05ffecec45d8098fd29e8ac1d1bf4f47abc1f4e6 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 11 Mar 2024 14:15:44 +0100 Subject: [PATCH 1/3] add a few NameServer role DNSSEC tests --- packages/conformance-tests/src/lib.rs | 1 + packages/conformance-tests/src/name_server.rs | 1 + .../src/name_server/rfc4035.rs | 1 + .../src/name_server/rfc4035/section_3.rs | 1 + .../rfc4035/section_3/section_3_1.rs | 1 + .../section_3/section_3_1/section_3_1_1.rs | 61 +++++++++++++++++++ 6 files changed, 66 insertions(+) create mode 100644 packages/conformance-tests/src/name_server.rs create mode 100644 packages/conformance-tests/src/name_server/rfc4035.rs create mode 100644 packages/conformance-tests/src/name_server/rfc4035/section_3.rs create mode 100644 packages/conformance-tests/src/name_server/rfc4035/section_3/section_3_1.rs create mode 100644 packages/conformance-tests/src/name_server/rfc4035/section_3/section_3_1/section_3_1_1.rs diff --git a/packages/conformance-tests/src/lib.rs b/packages/conformance-tests/src/lib.rs index dd939657..a92b491a 100644 --- a/packages/conformance-tests/src/lib.rs +++ b/packages/conformance-tests/src/lib.rs @@ -1,3 +1,4 @@ #![cfg(test)] +mod name_server; mod resolver; diff --git a/packages/conformance-tests/src/name_server.rs b/packages/conformance-tests/src/name_server.rs new file mode 100644 index 00000000..c7c01a74 --- /dev/null +++ b/packages/conformance-tests/src/name_server.rs @@ -0,0 +1 @@ +mod rfc4035; diff --git a/packages/conformance-tests/src/name_server/rfc4035.rs b/packages/conformance-tests/src/name_server/rfc4035.rs new file mode 100644 index 00000000..10712e9e --- /dev/null +++ b/packages/conformance-tests/src/name_server/rfc4035.rs @@ -0,0 +1 @@ +mod section_3; diff --git a/packages/conformance-tests/src/name_server/rfc4035/section_3.rs b/packages/conformance-tests/src/name_server/rfc4035/section_3.rs new file mode 100644 index 00000000..137bed61 --- /dev/null +++ b/packages/conformance-tests/src/name_server/rfc4035/section_3.rs @@ -0,0 +1 @@ +mod section_3_1; diff --git a/packages/conformance-tests/src/name_server/rfc4035/section_3/section_3_1.rs b/packages/conformance-tests/src/name_server/rfc4035/section_3/section_3_1.rs new file mode 100644 index 00000000..5656f46d --- /dev/null +++ b/packages/conformance-tests/src/name_server/rfc4035/section_3/section_3_1.rs @@ -0,0 +1 @@ +mod section_3_1_1; diff --git a/packages/conformance-tests/src/name_server/rfc4035/section_3/section_3_1/section_3_1_1.rs b/packages/conformance-tests/src/name_server/rfc4035/section_3/section_3_1/section_3_1_1.rs new file mode 100644 index 00000000..8477b76a --- /dev/null +++ b/packages/conformance-tests/src/name_server/rfc4035/section_3/section_3_1/section_3_1_1.rs @@ -0,0 +1,61 @@ +use dns_test::client::{Client, DigSettings}; +use dns_test::name_server::NameServer; +use dns_test::record::{Record, RecordType}; +use dns_test::{Network, Result, FQDN}; + +#[test] +fn rrsig_in_answer_section() -> Result<()> { + let network = Network::new()?; + + let ns = NameServer::new(&dns_test::subject(), FQDN::ROOT, &network)? + .sign()? + .start()?; + + let client = Client::new(&network)?; + let ns_fqdn = ns.fqdn(); + let ans = client.dig( + *DigSettings::default().dnssec(), + ns.ipv4_addr(), + RecordType::A, + ns_fqdn, + )?; + + assert!(ans.status.is_noerror()); + let [a, rrsig] = ans.answer.try_into().unwrap(); + + assert!(matches!(a, Record::A(..))); + let rrsig = rrsig.try_into_rrsig().unwrap(); + assert_eq!(RecordType::A, rrsig.type_covered); + assert_eq!(ns_fqdn, &rrsig.fqdn); + + Ok(()) +} + +#[test] +fn rrsig_in_authority_section() -> Result<()> { + let network = Network::new()?; + + let ns = NameServer::new(&dns_test::subject(), FQDN::ROOT, &network)? + .sign()? + .start()?; + + let client = Client::new(&network)?; + let ans = client.dig( + *DigSettings::default().dnssec(), + ns.ipv4_addr(), + RecordType::SOA, + &FQDN::ROOT, + )?; + + assert!(ans.status.is_noerror()); + let [ns, rrsig] = ans.authority.try_into().unwrap(); + + assert!(matches!(ns, Record::NS(..))); + let rrsig = rrsig.try_into_rrsig().unwrap(); + assert_eq!(RecordType::NS, rrsig.type_covered); + assert_eq!(FQDN::ROOT, rrsig.fqdn); + + Ok(()) +} + +// TODO Additional section From ce222b3de17d40b702f4b19a075241670b189164 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 11 Mar 2024 15:50:00 +0100 Subject: [PATCH 2/3] support Hickory in NameServer role note that because Hickory does not support pre-signed zone files all the DNSSEC tests fail with it --- .../section_3/section_3_1/section_3_1_1.rs | 3 +++ .../dns-test/src/docker/hickory.Dockerfile | 2 ++ packages/dns-test/src/implementation.rs | 23 ++++++------------- packages/dns-test/src/name_server.rs | 8 ------- .../templates/hickory.name-server.toml.jinja | 4 ++++ 5 files changed, 16 insertions(+), 24 deletions(-) create mode 100644 packages/dns-test/src/templates/hickory.name-server.toml.jinja diff --git a/packages/conformance-tests/src/name_server/rfc4035/section_3/section_3_1/section_3_1_1.rs b/packages/conformance-tests/src/name_server/rfc4035/section_3/section_3_1/section_3_1_1.rs index 8477b76a..20a1a9e3 100644 --- a/packages/conformance-tests/src/name_server/rfc4035/section_3/section_3_1/section_3_1_1.rs +++ b/packages/conformance-tests/src/name_server/rfc4035/section_3/section_3_1/section_3_1_1.rs @@ -4,6 +4,7 @@ use dns_test::record::{Record, RecordType}; use dns_test::{Network, Result, FQDN}; #[test] +#[ignore] fn rrsig_in_answer_section() -> Result<()> { let network = Network::new()?; @@ -32,6 +33,7 @@ fn rrsig_in_answer_section() -> Result<()> { } #[test] +#[ignore] fn rrsig_in_authority_section() -> Result<()> { let network = Network::new()?; @@ -59,3 +61,4 @@ fn rrsig_in_authority_section() -> Result<()> { } // TODO Additional section +// TODO TC bit diff --git a/packages/dns-test/src/docker/hickory.Dockerfile b/packages/dns-test/src/docker/hickory.Dockerfile index 77206244..18cd7555 100644 --- a/packages/dns-test/src/docker/hickory.Dockerfile +++ b/packages/dns-test/src/docker/hickory.Dockerfile @@ -1,7 +1,9 @@ FROM rust:1-slim-bookworm +# ldns-utils = ldns-{key2ds,keygen,signzone} RUN apt-get update && \ apt-get install -y \ + ldnsutils \ tshark # `dns-test` will invoke `docker build` from a temporary directory that contains diff --git a/packages/dns-test/src/implementation.rs b/packages/dns-test/src/implementation.rs index 1ec81e15..b22e0ae1 100644 --- a/packages/dns-test/src/implementation.rs +++ b/packages/dns-test/src/implementation.rs @@ -34,13 +34,6 @@ pub enum Role { Resolver, } -impl Role { - #[must_use] - pub fn is_resolver(&self) -> bool { - matches!(self, Self::Resolver) - } -} - #[derive(Clone)] pub enum Implementation { Bind, @@ -112,7 +105,12 @@ impl Implementation { ) } - Self::Hickory(_) => unimplemented!(), + Self::Hickory(_) => { + minijinja::render!( + include_str!("templates/hickory.name-server.toml.jinja"), + fqdn => origin.as_str() + ) + } }, } } @@ -134,14 +132,7 @@ impl Implementation { match self { Implementation::Bind => &["named", "-g", "-d5"], - Implementation::Hickory(_) => { - assert!( - role.is_resolver(), - "hickory acting in `NameServer` role is currently not supported" - ); - - &["hickory-dns", "-d"] - } + Implementation::Hickory(_) => &["hickory-dns", "-d"], Implementation::Unbound => match role { Role::NameServer => &["nsd", "-d"], diff --git a/packages/dns-test/src/name_server.rs b/packages/dns-test/src/name_server.rs index 3bef3fc3..37b1f160 100644 --- a/packages/dns-test/src/name_server.rs +++ b/packages/dns-test/src/name_server.rs @@ -156,14 +156,6 @@ impl NameServer { /// - one NS record, with this name server's FQDN set as the only available name server for /// the zone pub fn new(implementation: &Implementation, zone: FQDN, network: &Network) -> Result { - assert!( - matches!( - implementation, - Implementation::Unbound | Implementation::Bind - ), - "currently only `unbound` (`nsd`) and BIND can be used as a `NameServer`" - ); - let ns_count = ns_count(); let nameserver = primary_ns(ns_count); let image = implementation.clone().into(); diff --git a/packages/dns-test/src/templates/hickory.name-server.toml.jinja b/packages/dns-test/src/templates/hickory.name-server.toml.jinja new file mode 100644 index 00000000..1d784c86 --- /dev/null +++ b/packages/dns-test/src/templates/hickory.name-server.toml.jinja @@ -0,0 +1,4 @@ +[[zones]] +zone = "{{ fqdn }}" +zone_type = "Primary" +file = "/etc/zones/main.zone" From 74e479706138ae9fd66c57e3cd9cd17ca5ec82f4 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 11 Mar 2024 16:04:35 +0100 Subject: [PATCH 3/3] add a DNSSEC-disabled NameServer scenario test to ensure that hickory-dns is correctly configured to work in NameServer mode --- packages/conformance-tests/src/name_server.rs | 1 + .../src/name_server/scenarios.rs | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 packages/conformance-tests/src/name_server/scenarios.rs diff --git a/packages/conformance-tests/src/name_server.rs b/packages/conformance-tests/src/name_server.rs index c7c01a74..a2e4ef2b 100644 --- a/packages/conformance-tests/src/name_server.rs +++ b/packages/conformance-tests/src/name_server.rs @@ -1 +1,2 @@ mod rfc4035; +mod scenarios; diff --git a/packages/conformance-tests/src/name_server/scenarios.rs b/packages/conformance-tests/src/name_server/scenarios.rs new file mode 100644 index 00000000..17578ad7 --- /dev/null +++ b/packages/conformance-tests/src/name_server/scenarios.rs @@ -0,0 +1,23 @@ +use dns_test::client::{Client, DigSettings}; +use dns_test::name_server::NameServer; +use dns_test::record::RecordType; +use dns_test::{Network, Result, FQDN}; + +#[test] +fn authoritative_answer() -> Result<()> { + let network = &Network::new()?; + let ns = NameServer::new(&dns_test::subject(), FQDN::ROOT, network)?.start()?; + + let client = Client::new(network)?; + let ans = client.dig( + DigSettings::default(), + ns.ipv4_addr(), + RecordType::SOA, + &FQDN::ROOT, + )?; + + assert!(ans.status.is_noerror()); + assert!(ans.flags.authoritative_answer); + + Ok(()) +}