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

explore: make DNSSEC opt-in #31

Merged
merged 2 commits into from
May 22, 2024
Merged
Changes from all commits
Commits
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
134 changes: 100 additions & 34 deletions packages/dns-test/examples/explore.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::env;
use std::net::Ipv4Addr;
use std::sync::mpsc;

use dns_test::client::Client;
Expand All @@ -7,6 +9,8 @@ use dns_test::zone_file::Root;
use dns_test::{Network, Resolver, Result, TrustAnchor, FQDN};

fn main() -> Result<()> {
let args = Args::from_env()?;

let network = Network::new()?;
let peer = &dns_test::PEER;

Expand All @@ -21,32 +25,60 @@ fn main() -> Result<()> {
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.sign()?;
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 nameservers_ns = if args.dnssec {
let nameservers_ns = nameservers_ns.sign()?;
com_ns.add(nameservers_ns.ds().clone());
nameservers_ns.start()?
} else {
nameservers_ns.start()?
};

com_ns.referral(
nameservers_ns.zone().clone(),
nameservers_ns.fqdn().clone(),
nameservers_ns.ipv4_addr(),
);

let com_ns = if args.dnssec {
let com_ns = com_ns.sign()?;
root_ns.add(com_ns.ds().clone());
com_ns.start()?
} else {
com_ns.start()?
};

root_ns.referral(FQDN::COM, com_ns.fqdn().clone(), com_ns.ipv4_addr());

let mut trust_anchor = TrustAnchor::empty();
let root_ns = if args.dnssec {
let root_ns = root_ns.sign()?;
let root_ksk = root_ns.key_signing_key();
let root_zsk = root_ns.zone_signing_key();

trust_anchor.add(root_ksk.clone());
trust_anchor.add(root_zsk.clone());

root_ns.start()?
} else {
root_ns.start()?
};

println!("DONE");

let trust_anchor = TrustAnchor::from_iter([root_ksk.clone(), root_zsk.clone()]);
let client = Client::new(&network)?;
if args.dnssec {
// this will send queries to the loopback address and fail because there's no resolver
// but as a side-effect it will generate the `/etc/bind.keys` file we want
// ignore the expected error
let _ = client.delv(
Ipv4Addr::new(127, 0, 0, 1),
RecordType::SOA,
&FQDN::ROOT,
&trust_anchor,
)?;
}

println!("building docker image...");
let resolver = Resolver::new(
&network,
Expand All @@ -56,11 +88,6 @@ fn main() -> Result<()> {
.start(&dns_test::SUBJECT)?;
println!("DONE\n\n");

let resolver_addr = resolver.ipv4_addr();
let client = Client::new(&network)?;
// generate `/etc/bind.keys`
client.delv(resolver_addr, RecordType::SOA, &FQDN::ROOT, &trust_anchor)?;

let (tx, rx) = mpsc::channel();

ctrlc::set_handler(move || tx.send(()).expect("could not forward signal"))?;
Expand All @@ -86,7 +113,8 @@ fn main() -> Result<()> {
nameservers_ns.container_id()
);

println!("resolver's IP address: {resolver_addr}");
let resolver_addr = resolver.ipv4_addr();
println!("resolver's IP address: {resolver_addr}",);
println!(
"attach to this container with: `docker exec -it {} bash`\n",
resolver.container_id()
Expand All @@ -99,10 +127,13 @@ fn main() -> Result<()> {
);

println!("example queries (run these in the client container):\n");
println!("`dig @{resolver_addr} SOA .`\n");
println!(
"`delv -a /etc/bind.keys @{resolver_addr} SOA .` (you MUST use the `-a` flag with delv)\n\n"
);
let adflag = if args.dnssec { "+adflag" } else { "+noadflag" };
println!("`dig @{resolver_addr} {adflag} SOA .`\n");
if args.dnssec {
println!(
"`delv -a /etc/bind.keys @{resolver_addr} SOA .` (you MUST use the `-a` flag with delv)\n\n"
);
}

println!(
"to print the DNS traffic flowing through the resolver run this command in
Expand All @@ -118,3 +149,38 @@ the resolver container before performing queries:\n"

Ok(())
}

struct Args {
dnssec: bool,
}

impl Args {
fn from_env() -> Result<Self> {
let args: Vec<_> = env::args().skip(1).collect();
let num_args = args.len();

let dnssec = if num_args == 0 {
false
} else if num_args == 1 {
if args[0] == "--dnssec" {
true
} else {
return cli_error();
}
} else {
return cli_error();
};

Ok(Self { dnssec })
}
}

fn cli_error<T>() -> Result<T> {
eprintln!(
"usage: explore [--dnssec]
Options:
--dnssec sign zone files to enable DNSSEC"
);

Err("CLI error".into())
}