diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..85b60ca --- /dev/null +++ b/.env.sample @@ -0,0 +1 @@ +DYN_ROOT_ZONE= \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 2d5f9e1..8f8c8ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -331,6 +331,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + [[package]] name = "dtoa" version = "0.4.8" @@ -1142,6 +1148,7 @@ version = "0.1.0" dependencies = [ "clap-log-flag", "clap-verbosity-flag", + "dotenv", "futures 0.3.14", "log", "nest", diff --git a/Cargo.toml b/Cargo.toml index 26fc678..c69e78f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,3 +20,4 @@ trust-dns-client = "0.20.2" rocket = { git = "https://github.com/SergioBenitez/Rocket", branch = "master" } rocket_contrib = { git = "https://github.com/SergioBenitez/Rocket", branch = "master" } serde = "1.0.125" +dotenv = "0.15.0" \ No newline at end of file diff --git a/src/dns.rs b/src/dns.rs index 0e0fab0..8986a13 100644 --- a/src/dns.rs +++ b/src/dns.rs @@ -10,87 +10,91 @@ use trust_dns_client::rr::{LowerName, Name, RData, Record, RecordSet, RecordType use trust_dns_server::authority::{Catalog, ZoneType}; use trust_dns_server::server::ServerFuture; use trust_dns_server::store::in_memory::InMemoryAuthority; +use std::env; +use dotenv; static DEFAULT_TCP_REQUEST_TIMEOUT: u64 = 5; struct DnsManager { catalog: Catalog, + dyn_root_zone: String, } impl DnsManager { - pub fn new() -> DnsManager { + pub fn new(dyn_root_zone: String) -> DnsManager { let catalog: Catalog = Catalog::new(); return DnsManager { catalog, + dyn_root_zone, }; } +// +// pub fn upsert(&mut self, domain: String, ip: Ipv4Addr) { +// +// +// let authority_name = Name::from_str(&self.dyn_root_zone).unwrap(); +// +// let soa_serial = 1; +// let soa_name = Name::from_str(&self.dyn_root_zone).unwrap(); +// let soa_rdata = RData::SOA(SOA::new( +// Name::from_str(&self.dyn_root_zone).unwrap(), // mname +// Name::from_str(&format!("root.{}", &self.dyn_root_zone)).unwrap(), // rname +// soa_serial, // serial +// 604800, // refresh +// 86400, // retry +// 2419200, // expire +// 86400, // negtive cache ttl +// )); +// let mut soa_record_set = RecordSet::new(&soa_name, RecordType::SOA, soa_serial); +// soa_record_set.add_rdata(soa_rdata); +// let soa_rr_key = RrKey::new( +// LowerName::new(&authority_name), +// soa_record_set.record_type(), +// ); +// let mut authority_records = BTreeMap::new(); +// authority_records.insert(soa_rr_key, soa_record_set); +// +// let authority_zone_type = ZoneType::Master; +// let authority_allow_axfr = false; +// +// let mut authority = InMemoryAuthority::new( +// authority_name.clone(), +// authority_records, +// authority_zone_type, +// authority_allow_axfr, +// ) +// .unwrap(); +// +// /* +// let ns_name = Name::from_str("dyn.peachcloud.org.").unwrap(); +// let ns_ttl = 60; +// let ns_rdata = RData::NS(Name::from_str("localhost.").unwrap()); +// let ns_record = Record::from_rdata(ns_name, ns_ttl, ns_rdata); +// authority.upsert(ns_record, authority.serial()); +// */ +// +// let dyn_name = Name::from_str(&domain).unwrap(); +// let dyn_ttl = 60; +// let dyn_rdata = RData::A(ip); +// let dyn_record = Record::from_rdata(dyn_name, dyn_ttl, dyn_rdata); +// authority.upsert(dyn_record, authority.serial()); +// +// self.catalog.upsert( +// LowerName::new(&authority_name), +// Box::new(Arc::new(RwLock::new(authority))), +// ); +// } - pub fn upsert(&mut self, domain: String, ip: Ipv4Addr) { - - - let authority_name = Name::from_str("dyn.peachcloud.org.").unwrap(); - + fn get_initial_records(domain: &str) -> BTreeMap { + let authority_name = Name::from_str(domain).unwrap(); let soa_serial = 1; - let soa_name = Name::from_str("dyn.peachcloud.org.").unwrap(); + let soa_name = Name::from_str(domain).unwrap(); let soa_rdata = RData::SOA(SOA::new( - Name::from_str("dyn.peachcloud.org.").unwrap(), // mname - Name::from_str("root.dyn.peachcloud.org.").unwrap(), // rname - soa_serial, // serial - 604800, // refresh - 86400, // retry - 2419200, // expire - 86400, // negtive cache ttl - )); - let mut soa_record_set = RecordSet::new(&soa_name, RecordType::SOA, soa_serial); - soa_record_set.add_rdata(soa_rdata); - let soa_rr_key = RrKey::new( - LowerName::new(&authority_name), - soa_record_set.record_type(), - ); - let mut authority_records = BTreeMap::new(); - authority_records.insert(soa_rr_key, soa_record_set); - - let authority_zone_type = ZoneType::Master; - let authority_allow_axfr = false; - - let mut authority = InMemoryAuthority::new( - authority_name.clone(), - authority_records, - authority_zone_type, - authority_allow_axfr, - ) - .unwrap(); - - /* - let ns_name = Name::from_str("dyn.peachcloud.org.").unwrap(); - let ns_ttl = 60; - let ns_rdata = RData::NS(Name::from_str("localhost.").unwrap()); - let ns_record = Record::from_rdata(ns_name, ns_ttl, ns_rdata); - authority.upsert(ns_record, authority.serial()); - */ - - let dyn_name = Name::from_str(&domain).unwrap(); - let dyn_ttl = 60; - let dyn_rdata = RData::A(ip); - let dyn_record = Record::from_rdata(dyn_name, dyn_ttl, dyn_rdata); - authority.upsert(dyn_record, authority.serial()); - - self.catalog.upsert( - LowerName::new(&authority_name), - Box::new(Arc::new(RwLock::new(authority))), - ); - } - - fn get_initial_records(&mut self) -> BTreeMap { - let authority_name = Name::from_str("dyn.peachcloud.org.").unwrap(); - let soa_serial = 1; - let soa_name = Name::from_str("dyn.peachcloud.org.").unwrap(); - let soa_rdata = RData::SOA(SOA::new( - Name::from_str("dyn.peachcloud.org.").unwrap(), // mname - Name::from_str("root.dyn.peachcloud.org.").unwrap(), // rname + Name::from_str(domain).unwrap(), // mname + Name::from_str(&format!("root.{}", domain)).unwrap(), // rname soa_serial, // serial 604800, // refresh 86400, // retry @@ -108,19 +112,14 @@ impl DnsManager { authority_records } - fn upsert_test(&mut self) { + pub fn upsert(&mut self, domain: &str, ip: Ipv4Addr) { - let authority_records = self.get_initial_records(); - - let authority_name = Name::from_str("dyn.peachcloud.org.").unwrap(); + let authority_records = DnsManager::get_initial_records(domain); + let authority_name = Name::from_str(domain).unwrap(); let authority_zone_type = ZoneType::Master; let authority_allow_axfr = false; - // first upsert - let domain1 = "test.dyn.peachcloud.org"; - let ip1 = Ipv4Addr::new(1, 1, 1, 1); - let mut authority = InMemoryAuthority::new( authority_name.clone(), authority_records, @@ -129,67 +128,60 @@ impl DnsManager { ) .unwrap(); - let dyn_name = Name::from_str(domain1).unwrap(); + let dyn_name = Name::from_str(domain).unwrap(); let dyn_ttl = 60; - let dyn_rdata = RData::A(ip1); + let dyn_rdata = RData::A(ip); let dyn_record = Record::from_rdata(dyn_name, dyn_ttl, dyn_rdata); authority.upsert(dyn_record, authority.serial()); - let authority_ref = &authority; - self.catalog.upsert( LowerName::new(&authority_name), Box::new(Arc::new(RwLock::new(authority))), ); + } - // test second insert - let domain2 = "who.dyn.peachcloud.org"; + fn root_upsert(&mut self) { + let authority_records = DnsManager::get_initial_records(&self.dyn_root_zone); + let authority_name = Name::from_str(&self.dyn_root_zone).unwrap(); + + let authority_zone_type = ZoneType::Master; + let authority_allow_axfr = false; + + // first upsert, for root + let authority = InMemoryAuthority::new( + authority_name.clone(), + authority_records, + authority_zone_type, + authority_allow_axfr, + ) + .unwrap(); + self.catalog.upsert( + LowerName::new(&authority_name), + Box::new(Arc::new(RwLock::new(authority))), + ); + } + + + fn upsert_test(&mut self) { + + // first insert the authority for the root dyn zone + self.root_upsert(); + + // second upsert, for sub-sub + let domain1 = &format!("test.{}", self.dyn_root_zone); + let ip1 = Ipv4Addr::new(1, 1, 1, 1); + self.upsert(domain1, ip1); + + // third upsert, for sub-sub + let domain2 = &format!("peach.{}", self.dyn_root_zone); let ip2 = Ipv4Addr::new(1, 1, 1, 2); - let dyn_name = Name::from_str(domain2).unwrap(); - let dyn_ttl = 60; - let dyn_rdata = RData::A(ip2); - let dyn_record = Record::from_rdata(dyn_name, dyn_ttl, dyn_rdata); - authority.upsert(dyn_record, authority.serial()); + self.upsert(domain2, ip2); - // test if it worked - let dyn_name = Name::from_str(domain1).unwrap(); - let lower_name = LowerName::from(dyn_name); - let found = self.catalog.contains(&lower_name); - println!("++ found {:?}: {:?}", lower_name.to_string(), found); + // update upsert, for sub-sub + let domain2 = &format!("test.{}", self.dyn_root_zone); + let ip2 = Ipv4Addr::new(1, 1, 1, 3); + self.upsert(domain2, ip2); - let dyn_name = Name::from_str(domain2).unwrap(); - let lower_name = LowerName::from(dyn_name); - let found = self.catalog.contains(&lower_name); - println!("++ found {:?}: {:?}", lower_name.to_string(), found); - - let lower_name = LowerName::new(&authority_name); - let found = self.catalog.contains(&lower_name); - println!("++ found {:?}: {:?}", lower_name.to_string(), found); - - -// // second upsert -// let domain2 = "peach.dyn.peachcloud.org"; -// let ip2 = Ipv4Addr::new(1, 1, 1, 2); -// let authority_records = self.get_initial_records(); -// -// let mut authority = InMemoryAuthority::new( -// authority_name.clone(), -// authority_records, -// authority_zone_type, -// authority_allow_axfr, -// ) -// .unwrap(); -// -// let dyn_name = Name::from_str(domain2).unwrap(); -// let dyn_ttl = 60; -// let dyn_rdata = RData::A(ip2); -// let dyn_record = Record::from_rdata(dyn_name, dyn_ttl, dyn_rdata); -// authority.upsert(dyn_record, authority.serial()); -// -// self.catalog.upsert( -// LowerName::new(&authority_name), -// Box::new(Arc::new(RwLock::new(authority))), -// ); } } @@ -197,7 +189,9 @@ impl DnsManager { pub async fn server() -> ServerFuture { info!("Trust-DNS {} starting", trust_dns_server::version()); - let mut dns_manager = DnsManager::new(); + dotenv::from_path("/etc/peach-dyndns.conf").ok(); + let dyn_root_zone = env::var("DYN_ROOT_ZONE").expect("DYN_ROOT_ZONE not set"); + let mut dns_manager = DnsManager::new(dyn_root_zone.to_string()); // // first insert // dns_manager.upsert( @@ -241,5 +235,9 @@ pub async fn server() -> ServerFuture { server.register_listener(tcp_listener, tcp_request_timeout); info!("awaiting DNS connections..."); + let domain3 = &format!("question.{}", dns_manager.dyn_root_zone); + let ip3 = Ipv4Addr::new(1, 1, 1, 5); + dns_manager.upsert(domain3, ip3); + server }