Merge pull request #31 from ferrous-systems/ja-explore-opt-in-dnssec

`explore`: make DNSSEC opt-in
This commit is contained in:
Jorge Aparicio 2024-05-22 14:31:40 +02:00 committed by GitHub
commit 3a54e693fa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,3 +1,5 @@
use std::env;
use std::net::Ipv4Addr;
use std::sync::mpsc;
use dns_test::client::Client;
@ -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;
@ -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()?;
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()?
};
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();
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()?
};
let root_ns = 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,
@ -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"))?;
@ -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()
@ -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
@ -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())
}