Skip to content

Commit

Permalink
Merge pull request #20 from thibault-cne/issue/19
Browse files Browse the repository at this point in the history
Changed the configuration file
  • Loading branch information
thibault-cne authored Jul 30, 2024
2 parents 102c4c2 + cd949fb commit 36cc604
Show file tree
Hide file tree
Showing 10 changed files with 333 additions and 208 deletions.
33 changes: 15 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@

## How to use it?

In order to use the `dnsr` you have to create some configuration files and a folder to store the TSIG keys generated.
In order to use the `dnsr` you have to create a configuration file and a folder to store the TSIG keys generated.

`dnsr` is deployed as a Docker container. You can use the following command to run it:

```bash
docker run -d -p 8053:8053/udp -v ./config.yml:/etc/dnsr/config.yml -v ./domains.yml:/etc/dnsr/domains.yml -v ./keys:/etc/dnsr/keys ghrc.io/thibault-cne/dnsr:latest
docker run -d -p 8053:8053/udp -v ./config.yml:/etc/dnsr/config.yml -v ./keys:/etc/dnsr/keys ghrc.io/thibault-cne/dnsr:latest
```

### Configuration files
Expand All @@ -32,25 +32,22 @@ log:
enable_udp_metrics: true
# Enable the tcp metrics.
enable_tcp_metrics: true
```
#### domains.yml
The `domains.yml` file is used to configure the domains that the `dnsr` server will handle. In the following example, the `dnsr` server will handle the `example1.com`, `example2.com`, and `example3.com` domains:

```yaml
---
domains:
- example1.com
- name: example2.com
- name: example3.com
# The file name of the TSIG key for the domain.
# The file is located in the `tsig_folder` folder.
# This is optional. If not provided, the key file will be named after the domain name in snake case.
tsig_file_name: example3.key
# The keys and domains configuration
keys:
- key1:
- domain1
- domain2
- key2:
- domain3
- domain4
```
**Note:** The `dnsr` server constantly whatches the `domains.yml` file for changes. If the file is modified, the server will reload the domains (e.g. add or remove domains).
In the previous example, the `dnsr` server will handle the domain1, domain2, domain3 and domain4 domains.
The key1 will be used to handle the domain1 and domain2 domains and the key2 will be used to handle the domain3 and domain4 domains.

**Note**: The dnsr server constantly whatches the `config.yml` file for changes.
If the file is modified, the server will reload the domains (e.g. add or remove domains).

### TSIG keys

Expand Down
9 changes: 8 additions & 1 deletion config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,15 @@
# The log configuration.
log:
# The log level. This can be one of the following: trace, debug, info, warn, error, or off.
level: info
level: debug
# Enable the udp metrics.
enable_udp_metrics: true
# Enable the tcp metrics.
enable_tcp_metrics: true

keys:
key1:
- thibault-cne.fr
key2:
- example.com
- example.org
4 changes: 0 additions & 4 deletions domains.yml

This file was deleted.

15 changes: 10 additions & 5 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,24 @@ use std::path::Path;
use serde::Deserialize;

use crate::error::Result;
use crate::key::Keys;

pub const TSIG_PATH: &str = "/etc/dnsr/keys";
pub const BASE_CONFIG_FILE: &str = "/etc/dnsr/config.yml";
pub const DOMAIN_FILE: &str = "/etc/dnsr/domains.yml";

#[derive(Deserialize, Clone)]
#[derive(Deserialize, Clone, Debug)]
pub struct Config {
pub log: LogConfig,
pub keys: Option<Keys>,
}

impl Config {
pub fn domain_path(&self) -> &Path {
Path::new(DOMAIN_FILE)
pub fn take_keys(&mut self) -> Option<Keys> {
self.keys.take()
}

pub fn config_file_path() -> String {
std::env::var("DNSR_CONFIG").unwrap_or(BASE_CONFIG_FILE.into())
}

pub fn tsig_path(&self) -> &Path {
Expand All @@ -31,7 +36,7 @@ impl TryFrom<&Vec<u8>> for Config {
}
}

#[derive(Deserialize, Clone, Copy)]
#[derive(Deserialize, Clone, Copy, Debug)]
pub struct LogConfig {
#[serde(deserialize_with = "de_level_filter")]
pub level: log::LevelFilter,
Expand Down
45 changes: 34 additions & 11 deletions src/dns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ use domain::base::{Message, Name, Rtype, ToName};
use domain::net::server::message::Request;
use domain::net::server::service::{CallResult, ServiceError, Transaction, TransactionStream};
use domain::net::server::util::mk_builder_for_target;
use domain::zonetree::error::ZoneTreeModificationError;
use domain::zonetree::{Answer, ReadableZone, Rrset};
use domain::zonetree::{Zone, ZoneTree};
use domain::zonetree::{Answer, ReadableZone, Rrset, Zone};
use octseq::OctetsBuilder;

use crate::config::Config;
use crate::error::Error;
use crate::zone::ZoneTree;

type Zones = Arc<RwLock<ZoneTree>>;

Expand All @@ -31,21 +31,39 @@ impl State {
N: ToName,
F: FnOnce(Option<Box<dyn ReadableZone>>) -> Answer,
{
if class != Class::IN {
return Answer::new(Rcode::NXDOMAIN);
}

let zones = self.zones.read().unwrap();
f(zones.find_zone(qname, class).map(|z| z.read()))
f(zones.find_zone(qname).map(|z| z.read()))
}

pub fn insert_zone(&self, zone: Zone) -> Result<(), ZoneTreeModificationError> {
pub fn insert_zone(&self, zone: Zone) -> Result<(), Error> {
log::info!(target: "zone_change", "adding zone {}", zone.apex_name());
let mut zones = self.zones.write().unwrap();
zones.insert_zone(zone)
}

pub fn remove_zone<N>(&self, name: &N, class: Class) -> Result<(), ZoneTreeModificationError>
pub fn remove_zone<N>(&self, name: &N, class: Class) -> Result<(), Error>
where
N: ToName,
{
log::info!(target: "zone_change", "removing zone {} {}", name.to_bytes(), class);

let mut zones = self.zones.write().unwrap();
zones.remove_zone(name, class)

for z in zones.iter_zones() {
log::debug!(target: "zone", "zone {:?}", z);
}

zones.remove_zone(name)?;

for z in zones.iter_zones() {
log::debug!(target: "zone", "zone {}", z.apex_name());
}

Ok(())
}
}

Expand Down Expand Up @@ -99,14 +117,19 @@ async fn handle_axfr_request(
request: Request<Vec<u8>>,
state: Arc<State>,
) -> TransactionStream<Result<CallResult<Vec<u8>>, ServiceError>> {
let zones = state.zones.read().unwrap();
let mut stream = TransactionStream::default();

// Look up the zone for the queried name.
let question = request.message().sole_question().unwrap();
let zone = zones
.find_zone(question.qname(), question.qclass())
.map(|zone| zone.read());

if question.qclass() == Class::IN {
let answer = Answer::new(Rcode::NXDOMAIN);
add_to_stream(answer, request.message(), &mut stream);
return stream;
}

let zones = state.zones.read().unwrap();
let zone = zones.find_zone(question.qname()).map(|zone| zone.read());

// If not found, return an NXDOMAIN error response.
let Some(zone) = zone else {
Expand Down
165 changes: 0 additions & 165 deletions src/fs.rs

This file was deleted.

Loading

0 comments on commit 36cc604

Please sign in to comment.