enable multiple dns servers

This commit is contained in:
2025-12-05 15:12:17 +00:00
parent 45a20ffcdc
commit 860d95242e
7 changed files with 106 additions and 49 deletions

1
Cargo.lock generated
View File

@@ -161,6 +161,7 @@ name = "dns-comunications"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"dns-config",
"dns-update", "dns-update",
] ]

View File

@@ -1,7 +1,16 @@
[key] [zone]
root_domain = "root.domain.example"
[[server]]
conection_str = "tcp://127.0.0.1:53"
[server.key]
name = "key name" name = "key name"
value = "key in base64" value = "key in base64"
[zone] [[server]]
root_domain = "root.domain.example" conection_str = "udp://192.168.1.1:53"
conection_str = "tcp://127.0.0.1:53"
[server.key]
name = "key name"
value = "key in base64"

View File

@@ -6,3 +6,4 @@ edition = "2024"
[dependencies] [dependencies]
dns-update = "0.1" dns-update = "0.1"
base64 = "*" base64 = "*"
dns-config = {path = "../dns-config"}

View File

@@ -1,39 +1,53 @@
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use dns_update::{DnsRecord, DnsRecordType, DnsUpdater, TsigAlgorithm};
use base64::engine::general_purpose::STANDARD;
use base64::Engine; use base64::Engine;
use base64::engine::general_purpose::STANDARD;
use dns_update::{DnsUpdater, TsigAlgorithm};
use dns_config::ServerZonesConnection;
mod utils;
pub struct DnsManager { pub struct DnsManager {
pub dns_updater: DnsUpdater, pub dns_updaters: Vec<DnsUpdater>,
pub zone: String pub zone: String,
} }
impl DnsManager { impl DnsManager {
pub fn new(conection_str: String, key_name: String, key: String, zone: String) -> Self { pub fn new(zones_data: ServerZonesConnection) -> Result<Self, dns_update::Error> {
Self { let mut dns_updaters = Vec::new();
dns_updater: DnsUpdater::new_rfc2136_tsig( for zone_data in zones_data.servers_data {
conection_str, dns_updaters.push(DnsUpdater::new_rfc2136_tsig(
key_name, zone_data.conection_str,
STANDARD.decode(key).unwrap(), zone_data.key_name,
TsigAlgorithm::HmacSha256.into() #[allow(unreachable_code)]
).unwrap(), STANDARD.decode(zone_data.key).unwrap_or(continue),
zone TsigAlgorithm::HmacSha256.into(),
)?);
} }
Ok(Self {
dns_updaters,
zone: zones_data.root_domain,
})
} }
pub async fn add_domain(&self, domain_name: &String, domain_ip: Ipv4Addr) { pub async fn add_domain(
&self,
domain_name: &String,
domain_ip: Ipv4Addr,
) -> Result<(), dns_update::Error> {
let domain = format!("{}.{}", domain_name, self.zone); let domain = format!("{}.{}", domain_name, self.zone);
self.dns_updater.create( for dns_updater in &self.dns_updaters {
domain, utils::add_domain(dns_updater, &domain, &self.zone, domain_ip).await?;
DnsRecord::A { content: domain_ip }, }
300, Ok(())
self.zone.clone()
).await.unwrap();
} }
pub async fn del_domain(&self, domain_name: &String) { pub async fn del_domain(&self, domain_name: &String) -> Result<(), dns_update::Error> {
let domain = format!("{}.{}", domain_name, self.zone); let domain = format!("{}.{}", domain_name, self.zone);
self.dns_updater.delete(domain, self.zone.clone(), DnsRecordType::A).await.unwrap(); for dns_updater in &self.dns_updaters {
utils::del_domain(dns_updater, &domain, &self.zone).await?;
}
Ok(())
} }
} }

View File

@@ -0,0 +1,22 @@
use std::net::Ipv4Addr;
use dns_update::{DnsRecord, DnsRecordType, DnsUpdater};
pub async fn add_domain(
dns_updater: &DnsUpdater,
domain: &str,
zone: &str,
domain_ip: Ipv4Addr,
) -> Result<(), dns_update::Error> {
dns_updater
.create(domain, DnsRecord::A { content: domain_ip }, 300, zone)
.await
}
pub async fn del_domain(
dns_updater: &DnsUpdater,
domain: &str,
zone: &str,
) -> Result<(), dns_update::Error> {
dns_updater.delete(domain, zone, DnsRecordType::A).await
}

View File

@@ -1,36 +1,46 @@
use std::fs::read_to_string; use std::fs::read_to_string;
use toml::Table; use toml::Table;
pub struct KeyData { pub struct ZoneConnectionData {
pub conection_str: String,
pub key_name: String, pub key_name: String,
pub key: String, pub key: String,
} }
pub struct ZoneData { pub struct ServerZonesConnection {
pub root_domain: String, pub root_domain: String,
pub conection_str: String, pub servers_data: Vec<ZoneConnectionData>,
} }
impl KeyData { impl ZoneConnectionData {
pub fn get_config(file_name: &String) -> Self { pub fn get_config(file_name: &String) -> Vec<Self> {
let mut ret = Vec::new();
let key_toml = read_to_string(file_name).unwrap().parse::<Table>().unwrap(); let key_toml = read_to_string(file_name).unwrap().parse::<Table>().unwrap();
let name: String = key_toml["key"]["name"].as_str().unwrap().to_string(); for servers in key_toml["server"].as_array().unwrap() {
let value: String = key_toml["key"]["value"].as_str().unwrap().to_string(); let conection_str: String = servers["connection_str"].as_str().unwrap().to_string();
Self { let key_name: String = servers["key"]["name"].as_str().unwrap().to_string();
key_name: name, let key: String = servers["key"]["value"].as_str().unwrap().to_string();
key: value ret.push(Self {
conection_str,
key_name,
key,
});
} }
ret
} }
} }
impl ZoneData { impl ServerZonesConnection {
pub fn get_config(file_name: &String) -> Self { pub fn get_config(file_name: &String) -> Self {
let key_toml = read_to_string(file_name).unwrap().parse::<Table>().unwrap(); let key_toml = read_to_string(file_name).unwrap().parse::<Table>().unwrap();
let root_domain: String = key_toml["zone"]["root_domain"].as_str().unwrap().to_string(); let root_domain: String = key_toml["zone"]["root_domain"]
let conection_str: String = key_toml["zone"]["conection_str"].as_str().unwrap().to_string(); .as_str()
.unwrap()
.to_string();
Self { Self {
root_domain, root_domain,
conection_str servers_data: ZoneConnectionData::get_config(file_name),
} }
} }
} }

View File

@@ -5,14 +5,14 @@ use dns_config;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let key = dns_config::KeyData::get_config(&"config.toml".to_string()); let zone_data = dns_config::ServerZonesConnection::get_config(&"config.toml".to_string());
let zone = dns_config::ZoneData::get_config(&"config.toml".to_string()); let dns_manager = dns_comunications::DnsManager::new(zone_data).unwrap();
let dns_manager = dns_comunications::DnsManager::new(
zone.conection_str,
key.key_name,
key.key,
zone.root_domain);
dns_manager.add_domain(&"test001".to_string(), Ipv4Addr::from_str("1.1.1.1").unwrap()).await; _ = dns_manager
dns_manager.del_domain(&"test000".to_string()).await; .add_domain(
&"testzone".to_string(),
Ipv4Addr::from_str("1.1.1.1").unwrap(),
)
.await;
_ = dns_manager.del_domain(&"testzone".to_string()).await;
} }