Skip to content

Instantly share code, notes, and snippets.

@superboum
Created April 28, 2024 07:32
Show Gist options
  • Save superboum/eec903c00ffbc37d162e6d401d01280c to your computer and use it in GitHub Desktop.
Save superboum/eec903c00ffbc37d162e6d401d01280c to your computer and use it in GitHub Desktop.
Example of a custom Hickory Rust DNS server (custom Authority)
[package]
name = "dns"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = { version = "1", features = ["full"] }
hickory-server = "0.24.1"
hickory-proto = "0.24.1"
use std::future::Future;
use std::str::FromStr;
use std::pin::Pin;
use tokio::net::UdpSocket;
use hickory_proto::rr::*;
use hickory_server::authority::*;
use hickory_server::server::*;
struct StaticLookup(Vec<Record>);
impl LookupObject for StaticLookup {
fn is_empty(&self) -> bool {
false
}
fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Record> + Send + 'a> {
Box::new(self.0.iter())
}
fn take_additionals(&mut self) -> Option<Box<dyn LookupObject>> {
None
}
}
impl StaticLookup {
fn new() -> Self {
let mut rec = Record::new();
/*rec.set_name(Name::from_str(".").unwrap());
#rec.set_rr_type(RecordType::A);
rec.set_dns_class(DNSClass::IN);
rec.set_ttl(42);*/
Self(vec![rec])
}
}
struct HardcodedAuthority {}
impl AuthorityObject for HardcodedAuthority {
fn box_clone(&self) -> Box<dyn AuthorityObject> {
todo!()
}
fn zone_type(&self) -> ZoneType {
ZoneType::Primary
}
fn is_axfr_allowed(&self) -> bool {
todo!()
}
fn update<'life0, 'life1, 'async_trait>(
&'life0 self,
update: &'life1 MessageRequest,
) -> Pin<Box<dyn Future<Output = UpdateResult<bool>> + Send + 'async_trait>>
where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
{
todo!()
}
fn origin(&self) -> &LowerName {
todo!()
}
fn lookup<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 LowerName,
rtype: RecordType,
lookup_options: LookupOptions,
) -> Pin<
Box<dyn Future<Output = Result<Box<dyn LookupObject>, LookupError>> + Send + 'async_trait>,
>
where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
{
Box::pin(async {
Ok(Box::new(StaticLookup::new()) as Box<dyn LookupObject>)
})
}
fn search<'life0, 'life1, 'async_trait>(
&'life0 self,
request_info: RequestInfo<'life1>,
lookup_options: LookupOptions,
) -> Pin<
Box<dyn Future<Output = Result<Box<dyn LookupObject>, LookupError>> + Send + 'async_trait>,
>
where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
{
Box::pin(async {
Ok(Box::new(StaticLookup::new()) as Box<dyn LookupObject>)
})
}
fn get_nsec_records<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 LowerName,
lookup_options: LookupOptions,
) -> Pin<
Box<dyn Future<Output = Result<Box<dyn LookupObject>, LookupError>> + Send + 'async_trait>,
>
where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
{
todo!()
}
}
#[tokio::main]
async fn main() {
println!("hello");
let mut catalog: Catalog = Catalog::new();
catalog.upsert(
LowerName::from_str("deuxfleurs.fr").unwrap(),
Box::new(HardcodedAuthority {}),
);
let mut server = ServerFuture::new(catalog);
let udp_socket = UdpSocket::bind("0.0.0.0:5354").await.unwrap();
server.register_socket(udp_socket);
server.block_until_done().await.unwrap();
//runtime.block_on(server.block_until_done()).unwrap();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment