From 42fd9c0bcab47a3cdc6b1c84c19250e86133bfee Mon Sep 17 00:00:00 2001 From: Slatian Date: Fri, 24 Feb 2023 20:17:25 +0100 Subject: [PATCH] Made dns more useful --- src/simple_dns.rs | 249 +++++++++++++++++++++++++++---------------- templates/base.html | 8 +- templates/dig.html | 89 +++++++++++++++- templates/index.html | 4 +- 4 files changed, 254 insertions(+), 96 deletions(-) diff --git a/src/simple_dns.rs b/src/simple_dns.rs index 0742288..ff31fea 100644 --- a/src/simple_dns.rs +++ b/src/simple_dns.rs @@ -5,13 +5,17 @@ * It does not aim to be reusable for any other purpose, * the trust_dns_resolver library already does that. */ + +use trust_dns_proto::op::response_code::ResponseCode; use trust_dns_proto::rr::{ - record_type::RecordType, RData, + record_type::RecordType, }; use trust_dns_resolver::{ + error::ResolveError, + error::ResolveErrorKind, + lookup::Lookup, TokioAsyncResolver, - error::*, }; use std::net::IpAddr; @@ -21,12 +25,20 @@ use std::net::IpAddr; #[derive(serde::Deserialize, serde::Serialize, Default, Clone)] pub struct DnsLookupResult { - a: Vec, - aaaa: Vec, - cname: Vec, - mx: Vec, - ns: Vec, - soa: Vec, + a: Option>, + aaaa: Option>, + aname: Option>, + cname: Option>, + mx: Option>, + ns: Option>, + soa: Option>, + txt: Option>, + srv: Option>, + caa: Option>, + other_error: bool, + dns_error: bool, + nxdomain: bool, + timeout: bool, } #[derive(serde::Deserialize, serde::Serialize, Clone)] @@ -46,6 +58,14 @@ pub struct SoaRecord { minimum: u32, } +#[derive(serde::Deserialize, serde::Serialize, Clone)] +pub struct SrvRecord { + priority: u16, + weight: u16, + port: u16, + target: String, +} + /* Lookup Functions*/ pub async fn reverse_lookup( @@ -75,6 +95,114 @@ pub async fn reverse_lookup( } } +pub fn opush(opt_vec: &mut Option>, data: T) { + if opt_vec.is_none() { + *opt_vec = Some(Default::default()); + } + match opt_vec { + Some(vec) => vec.push(data), + None => {}, + } +} + +pub fn set_default_if_none(opt_vec: &mut Option>) { + match opt_vec { + Some(_) => {}, + None => { + *opt_vec = Some(Default::default()); + } + } +} + +pub fn add_record_to_lookup_result(result: &mut DnsLookupResult, record: &RData){ + match record { + RData::AAAA(address) => opush(&mut result.aaaa, std::net::IpAddr::V6(*address)), + RData::ANAME(aname) => opush(&mut result.aname, aname.to_string()), + RData::A(address) => opush(&mut result.a, std::net::IpAddr::V4(*address)), + RData::CAA(caa) => opush(&mut result.caa, caa.to_string()), + RData::CNAME(cname) => opush(&mut result.cname, cname.to_string()), + RData::MX(mx) => opush(&mut result.mx, MxRecord{ + preference: mx.preference(), + exchange: mx.exchange().to_string(), + }), + RData::NS(ns) => opush(&mut result.ns, ns.to_string()), + RData::SOA(soa) => opush(&mut result.soa, SoaRecord{ + mname: soa.mname().to_string(), + rname: soa.rname().to_string(), + serial: soa.serial(), + refresh: soa.refresh(), + retry: soa.retry(), + expire: soa.expire(), + minimum: soa.minimum(), + }), + RData::SRV(srv) => opush(&mut result.srv, SrvRecord{ + priority: srv.priority(), + weight: srv.weight(), + port: srv.port(), + target: srv.target().to_string(), + }), + RData::TXT(txt) => { + for text in txt.txt_data().iter() { + opush( + &mut result.txt, + String::from_utf8_lossy(text).into_owned() + ); + } + }, + _ => { println!("Tried to add an unkown DNS record to results: {record}"); }, + } +} + +pub fn integrate_lookup_result(dig_result: &mut DnsLookupResult, lookup_result: Result) { + match lookup_result { + Ok(lookup) => { + match lookup.query().query_type() { + RecordType::AAAA => set_default_if_none(&mut dig_result.aaaa), + RecordType::ANAME => set_default_if_none(&mut dig_result.aname), + RecordType::A => set_default_if_none(&mut dig_result.a), + RecordType::CAA => set_default_if_none(&mut dig_result.caa), + RecordType::CNAME => set_default_if_none(&mut dig_result.cname), + RecordType::MX => set_default_if_none(&mut dig_result.mx), + RecordType::NS => set_default_if_none(&mut dig_result.ns), + RecordType::SOA => set_default_if_none(&mut dig_result.soa), + RecordType::SRV => set_default_if_none(&mut dig_result.srv), + RecordType::TXT => set_default_if_none(&mut dig_result.txt), + _ => { /* This should not happen */ }, + }; + for record in lookup.iter() { + add_record_to_lookup_result(dig_result, record); + } + }, + Err(e) => { + match e.kind() { + ResolveErrorKind::Message(..) | + ResolveErrorKind::Msg(..) | + ResolveErrorKind::NoConnections | + ResolveErrorKind::Io(..) | + ResolveErrorKind::Proto(..) => { + dig_result.other_error = true; + println!("There was an error while doing a DNS Lookup: {e}"); + }, + ResolveErrorKind::Timeout => { + dig_result.timeout = true; + println!("There was a timeout while doing a DNS Lookup."); + }, + ResolveErrorKind::NoRecordsFound{response_code, ..} => { + match response_code { + ResponseCode::NXDomain => dig_result.nxdomain = true, + ResponseCode::NoError => {}, + _ => { + println!("The DNS Server returned an error while doing a DNS Lookup: {response_code}"); + dig_result.dns_error = true; + }, + } + } + _ => { /*Ignore for now*/ }, + } + } + } +} + // This function takes a resolver, a domain name and returns a DnsLookupResult. // If do_full_lookup is false only the A and AAAA (CNAMEs planned for the future) // records will be fetched. @@ -83,97 +211,34 @@ pub async fn lookup( name: &String, do_full_lookup: bool, ) -> DnsLookupResult { - let ipv4_lookup_res = resolver.ipv4_lookup(name); - let ipv6_lookup_res = resolver.ipv6_lookup(name); + let ipv4_lookup_res = resolver.lookup(name, RecordType::A); + let ipv6_lookup_res = resolver.lookup(name, RecordType::AAAA); let cname_lookup_res = resolver.lookup(name, RecordType::CNAME); + let aname_lookup_res = resolver.lookup(name, RecordType::ANAME); // initlize an empty lookup result let mut dig_result: DnsLookupResult = Default::default(); - match ipv4_lookup_res.await { - Ok(lookup) => { - for address in lookup { - dig_result.a.push(std::net::IpAddr::V4(address)); - } - } - Err(e) => { - println!("There was an error while looking A up {name}: {e}"); - } - } + integrate_lookup_result(&mut dig_result, ipv4_lookup_res.await); + integrate_lookup_result(&mut dig_result, ipv6_lookup_res.await); + integrate_lookup_result(&mut dig_result, cname_lookup_res.await); + integrate_lookup_result(&mut dig_result, aname_lookup_res.await); - match ipv6_lookup_res.await { - Ok(lookup) => { - for address in lookup { - dig_result.aaaa.push(std::net::IpAddr::V6(address)); - } - } - Err(e) => { - println!("There was an error while looking AAAA up {name}: {e}"); - } - } + //Don't do an extented lookup if the domain seemingly doesn't exist + if do_full_lookup && !dig_result.nxdomain { + let mx_lookup_res = resolver.lookup(name, RecordType::MX); + let ns_lookup_res = resolver.lookup(name, RecordType::NS); + let soa_lookup_res = resolver.lookup(name, RecordType::SOA); + let caa_lookup_res = resolver.lookup(name, RecordType::CAA); + let srv_lookup_res = resolver.lookup(name, RecordType::SRV); + let txt_lookup_res = resolver.lookup(name, RecordType::TXT); - match cname_lookup_res.await { - Ok(lookup) => { - for record in lookup { - match record { - RData::CNAME(cname) => dig_result.cname.push(cname.to_string()), - _ => {}, - } - } - } - Err(e) => { - println!("There was an error while looking CNAME up {name}: {e}"); - } - } - - if do_full_lookup { - let mx_lookup_res = resolver.mx_lookup(name); - let ns_lookup_res = resolver.ns_lookup(name); - let soa_lookup_res = resolver.soa_lookup(name); - - match mx_lookup_res.await { - Ok(lookup) => { - for mx in lookup { - dig_result.mx.push(MxRecord{ - preference: mx.preference(), - exchange: mx.exchange().to_string(), - }); - } - } - Err(e) => { - println!("There was an error while looking MX up {name}: {e}"); - } - } - - match ns_lookup_res.await { - Ok(lookup) => { - for ns in lookup { - dig_result.ns.push(ns.to_string()); - } - } - Err(e) => { - println!("There was an error while looking NS up {name}: {e}"); - } - } - - match soa_lookup_res.await { - Ok(lookup) => { - for soa in lookup { - dig_result.soa.push(SoaRecord{ - mname: soa.mname().to_string(), - rname: soa.rname().to_string(), - serial: soa.serial(), - refresh: soa.refresh(), - retry: soa.retry(), - expire: soa.expire(), - minimum: soa.minimum(), - }); - } - } - Err(e) => { - println!("There was an error while looking MX up {name}: {e}"); - } - } + integrate_lookup_result(&mut dig_result, mx_lookup_res.await); + integrate_lookup_result(&mut dig_result, ns_lookup_res.await); + integrate_lookup_result(&mut dig_result, soa_lookup_res.await); + integrate_lookup_result(&mut dig_result, caa_lookup_res.await); + integrate_lookup_result(&mut dig_result, srv_lookup_res.await); + integrate_lookup_result(&mut dig_result, txt_lookup_res.await); } diff --git a/templates/base.html b/templates/base.html index e4dbbf4..459c6ba 100644 --- a/templates/base.html +++ b/templates/base.html @@ -26,8 +26,9 @@