Skip to content
This repository has been archived by the owner on Jun 7, 2024. It is now read-only.

refactor Implementation branching into its own module #29

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
95cea68
support BIND in the NameServer role
japaric Feb 29, 2024
811e0ae
CI: test unbound (subject) against BIND (peers)
japaric Feb 29, 2024
eb498e6
refactor Implementation branching into its own module
japaric Feb 29, 2024
4f6c374
refactor: use builder pattern in Resolver ctor
japaric Mar 5, 2024
0b5bc32
allow enabling Extended DNS Errors (EDE)
japaric Mar 5, 2024
588b32a
parse EDE info from dig's output
japaric Mar 5, 2024
c0cc26d
extend DNSKEY API
japaric Mar 5, 2024
ccfae8b
add first EDE test
japaric Mar 5, 2024
0dfa39a
add name_server::Graph
japaric Mar 6, 2024
f530940
use Graph to simplify tests
japaric Mar 6, 2024
62a6541
add more EDE tests
japaric Mar 7, 2024
3dafa8a
add a few NameServer role DNSSEC tests
japaric Mar 11, 2024
294c702
support Hickory in NameServer role
japaric Mar 11, 2024
cf3a087
add a DNSSEC-disabled NameServer scenario test
japaric Mar 11, 2024
3731d8e
refactor: use builder pattern in Resolver ctor
japaric Mar 5, 2024
ad67207
Revert "refactor: use builder pattern in Resolver ctor"
listochkin Mar 28, 2024
659c6b9
refactor: use builder pattern in Resolver ctor
japaric Mar 5, 2024
69054d9
allow enabling Extended DNS Errors (EDE)
japaric Mar 5, 2024
79b8180
parse EDE info from dig's output
japaric Mar 5, 2024
1e36d37
extend DNSKEY API
japaric Mar 5, 2024
081d510
add first EDE test
japaric Mar 5, 2024
8d745c6
add name_server::Graph
japaric Mar 6, 2024
04c1c52
use Graph to simplify tests
japaric Mar 6, 2024
58a6220
add more EDE tests
japaric Mar 7, 2024
3610bdd
Merge pull request #41 from ferrous-systems/ja-hickory-name-server
listochkin Mar 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
run: cargo test -p dns-test -- --include-ignored

- name: Run tests against unbound
run: cargo test -p conformance-tests -- --include-ignored
run: DNS_TEST_PEER=bind cargo test -p conformance-tests -- --include-ignored

- name: Run tests against BIND
run: DNS_TEST_SUBJECT=bind cargo test -p conformance-tests -- --include-ignored
Expand Down
1 change: 1 addition & 0 deletions packages/conformance-tests/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![cfg(test)]

mod name_server;
mod resolver;
2 changes: 2 additions & 0 deletions packages/conformance-tests/src/name_server.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod rfc4035;
mod scenarios;
1 change: 1 addition & 0 deletions packages/conformance-tests/src/name_server/rfc4035.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod section_3;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod section_3_1;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod section_3_1_1;
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
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]
#[ignore]
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]
#[ignore]
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
// TODO TC bit
23 changes: 23 additions & 0 deletions packages/conformance-tests/src/name_server/scenarios.rs
Original file line number Diff line number Diff line change
@@ -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(())
}
69 changes: 20 additions & 49 deletions packages/conformance-tests/src/resolver/dns/scenarios.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use std::net::Ipv4Addr;

use dns_test::client::{Client, DigSettings};
use dns_test::name_server::NameServer;
use dns_test::name_server::{Graph, NameServer, Sign};
use dns_test::record::{Record, RecordType};
use dns_test::zone_file::Root;
use dns_test::{Network, Resolver, Result, TrustAnchor, FQDN};
use dns_test::{Network, Resolver, Result, FQDN};

#[test]
fn can_resolve() -> Result<()> {
Expand All @@ -13,34 +12,17 @@ fn can_resolve() -> Result<()> {

let network = Network::new()?;
let peer = dns_test::peer();
let mut root_ns = NameServer::new(&peer, FQDN::ROOT, &network)?;
let mut com_ns = NameServer::new(&peer, FQDN::COM, &network)?;

let mut nameservers_ns = NameServer::new(&peer, FQDN("nameservers.com.")?, &network)?;
nameservers_ns
.add(Record::a(root_ns.fqdn().clone(), root_ns.ipv4_addr()))
.add(Record::a(com_ns.fqdn().clone(), com_ns.ipv4_addr()))
.add(Record::a(needle_fqdn.clone(), expected_ipv4_addr));
let nameservers_ns = nameservers_ns.start()?;
let mut leaf_ns = NameServer::new(&peer, FQDN::NAMESERVERS, &network)?;
leaf_ns.add(Record::a(needle_fqdn.clone(), expected_ipv4_addr));

eprintln!("nameservers.com.zone:\n{}", nameservers_ns.zone_file());
let Graph {
nameservers: _nameservers,
root,
..
} = Graph::build(leaf_ns, Sign::No)?;

com_ns.referral(
nameservers_ns.zone().clone(),
nameservers_ns.fqdn().clone(),
nameservers_ns.ipv4_addr(),
);
let com_ns = com_ns.start()?;

eprintln!("com.zone:\n{}", com_ns.zone_file());

root_ns.referral(FQDN::COM, com_ns.fqdn().clone(), com_ns.ipv4_addr());
let root_ns = root_ns.start()?;

eprintln!("root.zone:\n{}", root_ns.zone_file());

let roots = &[Root::new(root_ns.fqdn().clone(), root_ns.ipv4_addr())];
let resolver = Resolver::start(&dns_test::subject(), roots, &TrustAnchor::empty(), &network)?;
let resolver = Resolver::new(&network, root).start(&dns_test::subject())?;
let resolver_ip_addr = resolver.ipv4_addr();

let client = Client::new(&network)?;
Expand All @@ -66,27 +48,16 @@ fn nxdomain() -> Result<()> {

let network = Network::new()?;
let peer = dns_test::peer();
let mut root_ns = NameServer::new(&peer, FQDN::ROOT, &network)?;
let mut com_ns = NameServer::new(&peer, FQDN::COM, &network)?;

let mut nameservers_ns = NameServer::new(&peer, FQDN("nameservers.com.")?, &network)?;
nameservers_ns
.add(Record::a(root_ns.fqdn().clone(), root_ns.ipv4_addr()))
.add(Record::a(com_ns.fqdn().clone(), com_ns.ipv4_addr()));
let nameservers_ns = nameservers_ns.start()?;

com_ns.referral(
nameservers_ns.zone().clone(),
nameservers_ns.fqdn().clone(),
nameservers_ns.ipv4_addr(),
);
let com_ns = com_ns.start()?;

root_ns.referral(FQDN::COM, com_ns.fqdn().clone(), com_ns.ipv4_addr());
let root_ns = root_ns.start()?;

let roots = &[Root::new(root_ns.fqdn().clone(), root_ns.ipv4_addr())];
let resolver = Resolver::start(&dns_test::subject(), roots, &TrustAnchor::empty(), &network)?;

let leaf_ns = NameServer::new(&peer, FQDN::NAMESERVERS, &network)?;

let Graph {
nameservers: _nameservers,
root,
..
} = Graph::build(leaf_ns, Sign::No)?;

let resolver = Resolver::new(&network, root).start(&dns_test::subject())?;
let resolver_ip_addr = resolver.ipv4_addr();

let client = Client::new(&network)?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,15 @@ use dns_test::name_server::NameServer;
use dns_test::record::RecordType;
use dns_test::tshark::{Capture, Direction};
use dns_test::zone_file::Root;
use dns_test::{Network, Resolver, Result, TrustAnchor, FQDN};
use dns_test::{Network, Resolver, Result, FQDN};

#[test]
#[ignore]
fn edns_support() -> Result<()> {
let network = &Network::new()?;
let ns = NameServer::new(&dns_test::peer(), FQDN::ROOT, network)?.start()?;
let resolver = Resolver::start(
&dns_test::subject(),
&[Root::new(ns.fqdn().clone(), ns.ipv4_addr())],
&TrustAnchor::empty(),
network,
)?;
let resolver = Resolver::new(network, Root::new(ns.fqdn().clone(), ns.ipv4_addr()))
.start(&dns_test::subject())?;

let mut tshark = resolver.eavesdrop()?;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
mod bogus;
mod ede;
mod secure;
87 changes: 34 additions & 53 deletions packages/conformance-tests/src/resolver/dnssec/scenarios/bogus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ use std::net::Ipv4Addr;

use base64::prelude::*;
use dns_test::client::{Client, DigSettings};
use dns_test::name_server::NameServer;
use dns_test::name_server::{Graph, NameServer, Sign};
use dns_test::record::{Record, RecordType};
use dns_test::zone_file::Root;
use dns_test::{Network, Resolver, Result, TrustAnchor, FQDN};
use dns_test::{Network, Resolver, Result, FQDN};

#[ignore]
#[test]
Expand All @@ -15,59 +14,41 @@ fn bad_signature_in_leaf_nameserver() -> Result<()> {

let network = Network::new()?;
let peer = dns_test::peer();
let mut root_ns = NameServer::new(&peer, FQDN::ROOT, &network)?;
let mut com_ns = NameServer::new(&peer, FQDN::COM, &network)?;

let mut nameservers_ns = NameServer::new(&peer, FQDN("nameservers.com.")?, &network)?;
nameservers_ns
.add(Record::a(root_ns.fqdn().clone(), root_ns.ipv4_addr()))
.add(Record::a(com_ns.fqdn().clone(), com_ns.ipv4_addr()))
.add(Record::a(needle_fqdn.clone(), expected_ipv4_addr));
let mut nameservers_ns = nameservers_ns.sign()?;

// fault injection: change the signature field of the RRSIG that covers the A record we'll query
let mut modified = 0;
for record in &mut nameservers_ns.signed_zone_file_mut().records {
if let Record::RRSIG(rrsig) = record {
if rrsig.fqdn == needle_fqdn {
let mut signature = BASE64_STANDARD.decode(&rrsig.signature)?;
let last = signature.last_mut().expect("empty signature");
*last = !*last;

rrsig.signature = BASE64_STANDARD.encode(&signature);
modified += 1;
let mut leaf_ns = NameServer::new(&peer, FQDN::NAMESERVERS, &network)?;
leaf_ns.add(Record::a(needle_fqdn.clone(), expected_ipv4_addr));

let Graph {
nameservers: _nameservers,
root,
trust_anchor,
} = Graph::build(
leaf_ns,
Sign::AndAmend(&|zone, records| {
if zone == &FQDN::NAMESERVERS {
let mut modified = 0;
for record in records {
if let Record::RRSIG(rrsig) = record {
if rrsig.fqdn == needle_fqdn {
let mut signature = BASE64_STANDARD.decode(&rrsig.signature).unwrap();
let last = signature.last_mut().expect("empty signature");
*last = !*last;

rrsig.signature = BASE64_STANDARD.encode(&signature);
modified += 1;
}
}
}

assert_eq!(modified, 1, "sanity check");
}
}
}
assert_eq!(modified, 1, "sanity check");

let nameservers_ds = nameservers_ns.ds().clone();
let nameservers_ns = nameservers_ns.start()?;

com_ns
.referral(
nameservers_ns.zone().clone(),
nameservers_ns.fqdn().clone(),
nameservers_ns.ipv4_addr(),
)
.add(nameservers_ds);
let com_ns = com_ns.sign()?;
let com_ds = com_ns.ds().clone();
let com_ns = com_ns.start()?;

root_ns
.referral(FQDN::COM, com_ns.fqdn().clone(), com_ns.ipv4_addr())
.add(com_ds);
let root_ns = root_ns.sign()?;
let root_ksk = root_ns.key_signing_key().clone();
let root_zsk = root_ns.zone_signing_key().clone();

let root_ns = root_ns.start()?;

let roots = &[Root::new(root_ns.fqdn().clone(), root_ns.ipv4_addr())];
}),
)?;

let trust_anchor = TrustAnchor::from_iter([root_ksk.clone(), root_zsk.clone()]);
let resolver = Resolver::start(&dns_test::subject(), roots, &trust_anchor, &network)?;
let trust_anchor = &trust_anchor.unwrap();
let resolver = Resolver::new(&network, root)
.trust_anchor(trust_anchor)
.start(&dns_test::subject())?;
let resolver_addr = resolver.ipv4_addr();

let client = Client::new(&network)?;
Expand Down
Loading