mirror of
https://codeberg.org/slatian/service.echoip-slatecave.git
synced 2025-07-16 22:13:30 +02:00
Made dns more useful
This commit is contained in:
@ -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<IpAddr>,
|
||||
aaaa: Vec<IpAddr>,
|
||||
cname: Vec<String>,
|
||||
mx: Vec<MxRecord>,
|
||||
ns: Vec<String>,
|
||||
soa: Vec<SoaRecord>,
|
||||
a: Option<Vec<IpAddr>>,
|
||||
aaaa: Option<Vec<IpAddr>>,
|
||||
aname: Option<Vec<String>>,
|
||||
cname: Option<Vec<String>>,
|
||||
mx: Option<Vec<MxRecord>>,
|
||||
ns: Option<Vec<String>>,
|
||||
soa: Option<Vec<SoaRecord>>,
|
||||
txt: Option<Vec<String>>,
|
||||
srv: Option<Vec<SrvRecord>>,
|
||||
caa: Option<Vec<String>>,
|
||||
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<T>(opt_vec: &mut Option<Vec<T>>, 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<T>(opt_vec: &mut Option<Vec<T>>) {
|
||||
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<Lookup, ResolveError>) {
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user