CDns-rs
v 1.0.0
An implementation of client side DNS query library which also is able to look for host name in /etc/hosts.
Also it is able to /etc/resolv.conf and uses options from this file to configure itself. So it acts like libc's gethostbyname(3) or gethostbyaddr(3). The configuration can be overriden.
This library supports both async and sync code. At the moment async part is not available because:
- it is based on the sync realization because async code is based on sync code and sync code is unstable at the moment
- it requires proper porting from sync, because sync uses
poll(2) to achieve the parallel name resolution
Supported
- Sending and receiving responses via TCP/UDP
- Reacting on the message truncated event by trying TCP
- Parsing /etc/hosts (all options)
- Partial parsing /etc/resolve.conf (all options)
- Async and Sync code (separate implementations)
- Sequential and pipelined requests.
- DNS-over-TLS
Extension
To use the DNS-over-TLS, the record to system's resolv.conf can be added:
nameserver 1.1.1.1#@853#cloudflare-dns.com
All after the # is considered as extension if there is no space between IP address and '#'.
ToDo
- DNS-over-HTTPS
- Parse /etc/nsswitch.conf
- DNSSEC
- OPT_NO_CHECK_NAMES
- resolv.conf (search, domain, sortlist)
Usage:
Simple Example:
use cdns_rs::sync::{QDns, QuerySetup, QType, request};
fn main()
{
let res_a = request::resolve_fqdn("protonmail.com", None).unwrap();
println!("A/AAAA:");
for a in res_a
{
println!("\t{}", a);
}
}
Custom query:
use cdns_rs::sync::{QDns, QuerySetup, QType, request, caches::CACHE};
fn main()
{
let mut dns_req =
QDns::make_empty(None, QuerySetup::default()).unwrap();
dns_req.add_request(QType::SOA, "protonmail.com");
let res = dns_req.query();
println!("SOA:");
let soa_res = res.get_result();
if soa_res.is_err() == true
{
println!("{}", soa_res.err().unwrap());
}
else
{
let soa = soa_res.unwrap();
if soa.is_empty() == true
{
println!("\tNo SOA found!")
}
else
{
for s in soa
{
for i in s.resp
{
println!("\t{}", i)
}
}
}
}
}
Custom resolv.conf use TCP:
use std::{net::{IpAddr, SocketAddr}, sync::Arc, time::Instant};
use cdns_rs::{cfg_resolv_parser::{OptionFlags, ResolveConfEntry}, common::bind_all, sync::{request, ResolveConfig}};
fn main()
{
let now = Instant::now();
let cfg =
"nameserver 8.8.8.8 \n\
options use-vc";
let resolver_ip: IpAddr = "8.8.8.8".parse().unwrap();
let mut resolve = ResolveConfig::default();
resolve.nameservers.push(Arc::new(ResolveConfEntry::new(SocketAddr::new(resolver_ip, 53), None, bind_all(resolver_ip)).unwrap()));
resolve.option_flags = OptionFlags::OPT_USE_VC;
let cust_parsed = Arc::new(ResolveConfig::custom_config(cfg).unwrap());
let cust_manual = Arc::new(resolve);
assert_eq!(cust_parsed, cust_manual);
let res_a = request::resolve_fqdn("protonmail.com", Some(cust_parsed)).unwrap();
let elapsed = now.elapsed();
println!("Elapsed: {:.2?}", elapsed);
println!("A/AAAA:");
for a in res_a
{
println!("\t{}", a);
}
return;
}
Custom resolv.conf use TLS:
use std::{sync::Arc, time::Instant};
use cdns_rs::sync::{request, ResolveConfig};
fn main()
{
let now = Instant::now();
let cfg = "nameserver 1.1.1.1#@853#cloudflare-dns.com \n\
options use-vc single-request";
let cust = Arc::new(ResolveConfig::custom_config(cfg).unwrap());
let res_a = request::resolve_fqdn("google.com", Some(cust.clone())).unwrap();
let elapsed = now.elapsed();
println!("Elapsed: {:.2?}", elapsed);
println!("A/AAAA:");
for a in res_a
{
println!("\t{}", a);
}
return;
}
ToSockAddress
use std::net::UdpSocket;
use cdns_rs::sync::query::QDnsSockerAddr;
fn main()
{
let udp = UdpSocket::bind("127.0.0.1:33333").unwrap();
udp.connect(QDnsSockerAddr::resolve("localhost:44444").unwrap()).unwrap();
udp.send("test".as_bytes()).unwrap();
return;
}