Commit 1a238ea0 authored by bksp's avatar bksp
Browse files

bootstrap project

parent 75ea6f92
/target
config.toml
This diff is collapsed.
[package]
name = "nomilo"
version = "0.1.0-dev"
authors = ["Gaël Berthaud-Müller <blacksponge@tuta.io>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
trust-dns-client = "0.20.1"
trust-dns-proto = "0.20.1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rocket = "0.4.7"
rocket_contrib = { version = "0.4", default-features = false, features = ["json"]}
toml = "0.5"
[dns_server]
address = "127.0.0.1:53"
use std::net::SocketAddr;
use std::path::PathBuf;
use std::fs;
use serde::{Deserialize};
use toml;
#[derive(Deserialize)]
pub struct Config {
pub dns_server: DnsServerConfig
}
#[derive(Deserialize)]
pub struct DnsServerConfig {
pub address: SocketAddr
}
pub fn load(file_name: PathBuf) -> Config {
toml::from_str(&fs::read_to_string(file_name).expect("could not read config file")).expect("could not parse config file")
}
#![feature(proc_macro_hygiene, decl_macro)]
use std::str::FromStr;
#[macro_use] extern crate rocket;
use rocket::State;
use rocket_contrib::json::Json;
use trust_dns_client::client::{Client, SyncClient};
use trust_dns_client::tcp::TcpClientConnection;
use trust_dns_client::op::DnsResponse;
use trust_dns_client::rr::{DNSClass, Name, Record, RecordType};
mod types;
mod config;
#[get("/zones/<zone>/records")]
fn zone_records(client: State<SyncClient<TcpClientConnection>>, zone: String) -> Json<Vec<types::dns::Record>> {
// TODO: Implement FromParam for Name
let name = Name::from_str(&zone).unwrap();
// TODO: add support for all trust-dns record types
// then use AXFR here and filter out dnssec related fields
let response: DnsResponse = client.query(&name, DNSClass::IN, RecordType::AAAA).unwrap();
let answers: &[Record] = response.answers();
let records: Vec<types::dns::Record> = answers.to_vec().into_iter().map(|record| record.into()).collect();
Json(records)
}
fn main() {
let app_config = config::load("config.toml".into());
let conn = TcpClientConnection::new(app_config.dns_server.address).unwrap();
let client = SyncClient::new(conn);
rocket::ignite()
.manage(client)
.mount("/api/v1", routes![zone_records]).launch();
}
use std::net::{Ipv6Addr, Ipv4Addr};
use serde::{Serialize, Deserialize};
pub mod trust_dns_types {
pub use trust_dns_client::rr::rdata::{
DNSSECRecordType, NULL,
};
pub use trust_dns_client::rr::{
RecordType, RData, DNSClass, Record
};
pub use trust_dns_proto::rr::Name;
}
#[derive(Deserialize, Serialize)]
pub enum RecordType {
A,
AAAA,
ANAME,
ANY,
AXFR,
CAA,
CNAME,
HINFO,
HTTPS,
IXFR,
MX,
NAPTR,
NS,
NULL,
OPENPGPKEY,
OPT,
PTR,
SOA,
SRV,
SSHFP,
SVCB,
TLSA,
TXT,
// dnssec
DNSKEY,
DS,
KEY,
NSEC,
NSEC3,
NSEC3PARAM,
RRSIG,
SIG,
Unknown(u16),
ZERO,
}
impl From<trust_dns_types::RecordType> for RecordType {
fn from(record_type: trust_dns_types::RecordType) -> RecordType {
match record_type {
trust_dns_types::RecordType::A => RecordType::A,
trust_dns_types::RecordType::AAAA => RecordType::AAAA,
trust_dns_types::RecordType::ANAME => RecordType::ANAME,
trust_dns_types::RecordType::ANY => RecordType::ANY,
trust_dns_types::RecordType::AXFR => RecordType::AXFR,
trust_dns_types::RecordType::CAA => RecordType::CAA,
trust_dns_types::RecordType::CNAME => RecordType::CNAME,
trust_dns_types::RecordType::HINFO => RecordType::HINFO,
trust_dns_types::RecordType::HTTPS => RecordType::HTTPS,
trust_dns_types::RecordType::IXFR => RecordType::IXFR,
trust_dns_types::RecordType::MX => RecordType::MX,
trust_dns_types::RecordType::NAPTR => RecordType::NAPTR,
trust_dns_types::RecordType::NS => RecordType::NS,
trust_dns_types::RecordType::NULL => RecordType::NULL,
trust_dns_types::RecordType::OPENPGPKEY => RecordType::OPENPGPKEY,
trust_dns_types::RecordType::OPT => RecordType::OPT,
trust_dns_types::RecordType::PTR => RecordType::PTR,
trust_dns_types::RecordType::SOA => RecordType::SOA,
trust_dns_types::RecordType::SRV => RecordType::SRV,
trust_dns_types::RecordType::SSHFP => RecordType::SSHFP,
trust_dns_types::RecordType::SVCB => RecordType::SVCB,
trust_dns_types::RecordType::TLSA => RecordType::TLSA,
trust_dns_types::RecordType::TXT => RecordType::TXT,
trust_dns_types::RecordType::DNSSEC(trust_dns_types::DNSSECRecordType::DNSKEY) => RecordType::DNSKEY,
trust_dns_types::RecordType::DNSSEC(trust_dns_types::DNSSECRecordType::DS) => RecordType::DS,
trust_dns_types::RecordType::DNSSEC(trust_dns_types::DNSSECRecordType::KEY) => RecordType::KEY,
trust_dns_types::RecordType::DNSSEC(trust_dns_types::DNSSECRecordType::NSEC) => RecordType::NSEC,
trust_dns_types::RecordType::DNSSEC(trust_dns_types::DNSSECRecordType::NSEC3) => RecordType::NSEC3,
trust_dns_types::RecordType::DNSSEC(trust_dns_types::DNSSECRecordType::NSEC3PARAM) => RecordType::NSEC3PARAM,
trust_dns_types::RecordType::DNSSEC(trust_dns_types::DNSSECRecordType::RRSIG) => RecordType::RRSIG,
trust_dns_types::RecordType::DNSSEC(trust_dns_types::DNSSECRecordType::SIG) => RecordType::SIG,
trust_dns_types::RecordType::DNSSEC(trust_dns_types::DNSSECRecordType::Unknown(r#type)) => RecordType::Unknown(r#type),
trust_dns_types::RecordType::Unknown(r#type) => RecordType::Unknown(r#type),
trust_dns_types::RecordType::ZERO => RecordType::ZERO,
}
}
}
impl Into<trust_dns_types::RecordType> for RecordType {
fn into(self) -> trust_dns_types::RecordType {
match self {
RecordType::A => trust_dns_types::RecordType::A,
RecordType::AAAA => trust_dns_types::RecordType::AAAA,
RecordType::ANAME => trust_dns_types::RecordType::ANAME,
RecordType::ANY => trust_dns_types::RecordType::ANY,
RecordType::AXFR => trust_dns_types::RecordType::AXFR,
RecordType::CAA => trust_dns_types::RecordType::CAA,
RecordType::CNAME => trust_dns_types::RecordType::CNAME,
RecordType::HINFO => trust_dns_types::RecordType::HINFO,
RecordType::HTTPS => trust_dns_types::RecordType::HTTPS,
RecordType::IXFR => trust_dns_types::RecordType::IXFR,
RecordType::MX => trust_dns_types::RecordType::MX,
RecordType::NAPTR => trust_dns_types::RecordType::NAPTR,
RecordType::NS => trust_dns_types::RecordType::NS,
RecordType::NULL => trust_dns_types::RecordType::NULL,
RecordType::OPENPGPKEY => trust_dns_types::RecordType::OPENPGPKEY,
RecordType::OPT => trust_dns_types::RecordType::OPT,
RecordType::PTR => trust_dns_types::RecordType::PTR,
RecordType::SOA => trust_dns_types::RecordType::SOA,
RecordType::SRV => trust_dns_types::RecordType::SRV,
RecordType::SSHFP => trust_dns_types::RecordType::SSHFP,
RecordType::SVCB => trust_dns_types::RecordType::SVCB,
RecordType::TLSA => trust_dns_types::RecordType::TLSA,
RecordType::TXT => trust_dns_types::RecordType::TXT,
RecordType::DNSKEY => trust_dns_types::RecordType::DNSSEC(trust_dns_types::DNSSECRecordType::DNSKEY),
RecordType::DS => trust_dns_types::RecordType::DNSSEC(trust_dns_types::DNSSECRecordType::DS),
RecordType::KEY => trust_dns_types::RecordType::DNSSEC(trust_dns_types::DNSSECRecordType::KEY),
RecordType::NSEC => trust_dns_types::RecordType::DNSSEC(trust_dns_types::DNSSECRecordType::NSEC),
RecordType::NSEC3 => trust_dns_types::RecordType::DNSSEC(trust_dns_types::DNSSECRecordType::NSEC3),
RecordType::NSEC3PARAM => trust_dns_types::RecordType::DNSSEC(trust_dns_types::DNSSECRecordType::NSEC3PARAM),
RecordType::RRSIG => trust_dns_types::RecordType::DNSSEC(trust_dns_types::DNSSECRecordType::RRSIG),
RecordType::SIG => trust_dns_types::RecordType::DNSSEC(trust_dns_types::DNSSECRecordType::SIG),
RecordType::Unknown(r#type) => trust_dns_types::RecordType::Unknown(r#type),
RecordType::ZERO => trust_dns_types::RecordType::ZERO,
}
}
}
#[derive(Deserialize, Serialize)]
#[serde(tag = "Type")]
pub enum RData {
#[serde(rename_all = "PascalCase")]
A {
address: Ipv4Addr
},
#[serde(rename_all = "PascalCase")]
AAAA {
address: Ipv6Addr
},
ANAME(StringName),
// CAA(CAA),
CNAME(StringName),
// HINFO(HINFO),
// HTTPS(SVCB),
// MX(MX),
// NAPTR(NAPTR),
NULL(NULL),
NS(StringName),
// OPENPGPKEY(OPENPGPKEY),
// OPT(OPT),
PTR(StringName),
// SOA(SOA),
// SRV(SRV),
// SSHFP(SSHFP),
// SVCB(SVCB),
// TLSA(TLSA),
// TXT(TXT),
// DNSSEC(DNSSECRData),
Unknown {
code: u16,
rdata: NULL,
},
// ZERO,
}
impl From<trust_dns_types::RData> for RData {
fn from(rdata: trust_dns_types::RData) -> RData {
match rdata {
trust_dns_types::RData::A(address) => RData::A { address },
trust_dns_types::RData::AAAA(address) => RData::AAAA { address },
_ => unimplemented!()
}
}
}
#[derive(Deserialize, Serialize)]
pub struct StringName(String);
impl From<trust_dns_types::Name> for StringName {
fn from(name: trust_dns_types::Name) -> StringName {
StringName(name.to_utf8())
}
}
#[derive(Deserialize, Serialize)]
pub struct NULL {
pub anything: Option<Vec<u8>>,
}
impl From<trust_dns_types::NULL> for NULL {
fn from(null: trust_dns_types::NULL) -> NULL {
NULL {
anything: null.anything().map(|e| e.to_vec())
}
}
}
#[derive(Deserialize, Serialize)]
pub enum DNSClass {
IN,
CH,
HS,
NONE,
ANY,
OPT(u16),
}
impl From<trust_dns_types::DNSClass> for DNSClass {
fn from(dns_class: trust_dns_types::DNSClass) -> DNSClass {
match dns_class {
trust_dns_types::DNSClass::IN => DNSClass::IN,
trust_dns_types::DNSClass::CH => DNSClass::CH,
trust_dns_types::DNSClass::HS => DNSClass::HS,
trust_dns_types::DNSClass::NONE => DNSClass::NONE,
trust_dns_types::DNSClass::ANY => DNSClass::ANY,
trust_dns_types::DNSClass::OPT(v) => DNSClass::OPT(v),
}
}
}
#[derive(Deserialize, Serialize)]
pub struct Record {
#[serde(rename = "Name")]
name: StringName,
//#[serde(rename = "Type")]
//rr_type: RecordType,
#[serde(rename = "Class")]
dns_class: DNSClass,
#[serde(rename = "TTL")]
ttl: u32,
#[serde(flatten)]
rdata: RData,
}
impl From<trust_dns_types::Record> for Record {
fn from(record: trust_dns_types::Record) -> Record {
Record {
name: StringName(record.name().to_utf8()),
//rr_type: record.rr_type().into(),
dns_class: record.dns_class().into(),
ttl: record.ttl(),
rdata: record.into_data().into(),
}
}
}
pub mod dns;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment