10 releases (1 stable)
Uses new Rust 2024
new 1.0.0 | Apr 6, 2025 |
---|---|
0.4.0 | Feb 28, 2025 |
0.3.0 | Oct 30, 2024 |
0.2.6 | Mar 24, 2024 |
0.1.1 | Nov 7, 2021 |
#1230 in Network programming
86 downloads per month
Used in ipfw-rs
350KB
8K
SLoC
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:
- see ./examples/
Simple Example:
use cdns_rs::sync::{QDns, QuerySetup, QType, request};
fn main()
{
// a, aaaa
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()
{
// soa
let mut dns_req =
QDns::make_empty(None, QuerySetup::default()).unwrap();
dns_req.add_request(QType::SOA, "protonmail.com");
// sending request and receiving results
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";
// -- or --
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);
// a, aaaa
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());
// a, aaaa
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;
// run in shell `nc -u -l 44444` a "test" should be received
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;
}
Dependencies
~14–24MB
~410K SLoC