From ba96f014ef0766913e35a69ec1fa9322b3df2b5e Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Sat, 21 Sep 2019 12:18:27 +0200 Subject: [PATCH] Make DNS cache TTLs configurable --- encrypted-dns.toml | 15 +++++++++++++++ src/cache.rs | 39 +++++++++++++++++++++++++++++++++++++-- src/config.rs | 3 +++ src/globals.rs | 7 ++----- src/main.rs | 13 +++++++++---- 5 files changed, 66 insertions(+), 11 deletions(-) diff --git a/encrypted-dns.toml b/encrypted-dns.toml index c8a357a..c07f85d 100644 --- a/encrypted-dns.toml +++ b/encrypted-dns.toml @@ -56,6 +56,21 @@ tcp_max_active_connections = 100 cache_capacity = 10000 +## DNS cache: minimum TTL + +cache_ttl_min = 600 + + +## DNS cache: max TTL + +cache_ttl_max = 86400 + + +## DNS cache: error TTL + +cache_ttl_error = 600 + + ## User name to drop privileges to, when started as root. # user = "nobody" diff --git a/src/cache.rs b/src/cache.rs index 676ed7c..7737f3a 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -1,6 +1,9 @@ use crate::dns; +use clockpro_cache::ClockProCache; use coarsetime::{Duration, Instant}; +use parking_lot::{Mutex, MutexGuard}; +use std::sync::Arc; #[derive(Clone, Debug)] pub struct CachedResponse { @@ -9,8 +12,9 @@ pub struct CachedResponse { } impl CachedResponse { - pub fn new(response: Vec) -> Self { - let ttl = dns::min_ttl(&response, 1, 86400, 3600).unwrap_or(3600); + pub fn new(cache: &Cache, response: Vec) -> Self { + let ttl = dns::min_ttl(&response, cache.ttl_min, cache.ttl_max, cache.ttl_error) + .unwrap_or(cache.ttl_error); let expiry = Instant::recent() + Duration::from_secs(u64::from(ttl)); CachedResponse { response, expiry } } @@ -27,3 +31,34 @@ impl CachedResponse { Instant::recent() > self.expiry } } + +#[derive(Clone, Derivative)] +#[derivative(Debug)] +pub struct Cache { + #[derivative(Debug = "ignore")] + cache: Arc>>, + ttl_min: u32, + ttl_max: u32, + ttl_error: u32, +} + +impl Cache { + pub fn new( + clockpro_cache: ClockProCache, + ttl_min: u32, + ttl_max: u32, + ttl_error: u32, + ) -> Self { + Cache { + cache: Arc::new(Mutex::new(clockpro_cache)), + ttl_min, + ttl_max, + ttl_error, + } + } + + #[inline] + pub fn lock(&self) -> MutexGuard> { + self.cache.lock() + } +} diff --git a/src/config.rs b/src/config.rs index 95f4e24..d81dc76 100644 --- a/src/config.rs +++ b/src/config.rs @@ -31,6 +31,9 @@ pub struct Config { pub udp_max_active_connections: u32, pub tcp_max_active_connections: u32, pub cache_capacity: usize, + pub cache_ttl_min: u32, + pub cache_ttl_max: u32, + pub cache_ttl_error: u32, pub user: Option, pub group: Option, pub chroot: Option, diff --git a/src/globals.rs b/src/globals.rs index 7ec8040..fe3a073 100644 --- a/src/globals.rs +++ b/src/globals.rs @@ -2,7 +2,6 @@ use crate::cache::*; use crate::crypto::*; use crate::dnscrypt_certs::*; -use clockpro_cache::ClockProCache; use parking_lot::{Mutex, RwLock}; use siphasher::sip128::SipHasher13; use std::collections::vec_deque::VecDeque; @@ -14,8 +13,7 @@ use std::time::Duration; use tokio::runtime::Runtime; use tokio::sync::oneshot; -#[derive(Derivative)] -#[derivative(Debug)] +#[derive(Debug, Clone)] pub struct Globals { pub runtime: Arc, pub state_file: PathBuf, @@ -36,6 +34,5 @@ pub struct Globals { pub tcp_active_connections: Arc>>>, pub key_cache_capacity: usize, pub hasher: SipHasher13, - #[derivative(Debug = "ignore")] - pub cache: Arc>>, + pub cache: Cache, } diff --git a/src/main.rs b/src/main.rs index 58100e7..a2143de 100644 --- a/src/main.rs +++ b/src/main.rs @@ -222,7 +222,7 @@ async fn resolve(globals: &Globals, mut packet: &mut Vec) -> Result, return Ok(cached_response.into_response()); } } else { - let cached_response = CachedResponse::new(response.clone()); + let cached_response = CachedResponse::new(&globals.cache, response.clone()); globals.cache.lock().insert(packet_hash, cached_response); } dns::set_tid(&mut response, original_tid); @@ -537,8 +537,13 @@ fn main() -> Result<(), Error> { let (sh_k0, sh_k1) = rand::thread_rng().gen(); let hasher = SipHasher13::new_with_keys(sh_k0, sh_k1); - let cache = ClockProCache::new(cache_capacity) - .map_err(|e| format_err!("Unable to create the DNS cache: [{}]", e))?; + let cache = Cache::new( + ClockProCache::new(cache_capacity) + .map_err(|e| format_err!("Unable to create the DNS cache: [{}]", e))?, + config.cache_ttl_min, + config.cache_ttl_max, + config.cache_ttl_error, + ); let globals = Arc::new(Globals { runtime: runtime.clone(), @@ -566,7 +571,7 @@ fn main() -> Result<(), Error> { ))), key_cache_capacity, hasher, - cache: Arc::new(Mutex::new(cache)), + cache, }); let updater = DNSCryptEncryptionParamsUpdater::new(globals.clone()); if !state_is_new {