diff --git a/README.md b/README.md index d2d0690..579ae3f 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ A new server-side proxy for encrypted DNS, written in Rust, supporting: Distinctive features: - Trivial to set up. Keys, certificates and stamps are automatically created and renewed without requiring any external scripts. +- Keys can be imported from `dnscrypt-wrapper`. - Serve all protocols on the same IP and port. Yes, you can serve both DNSCrypt and DoH on port 443. - Caching. - Anonymized DNSCrypt. @@ -17,4 +18,4 @@ Distinctive features: - Local filtering. - Windows support. -# *** This is a work in progress - Nothing to see yet *** +## *** This is a work in progress - Nothing to see yet *** diff --git a/encrypted-dns.toml b/encrypted-dns.toml index 5d693dd..e2071dc 100644 --- a/encrypted-dns.toml +++ b/encrypted-dns.toml @@ -72,7 +72,7 @@ tcp_max_active_connections = 100 [dnscrypt] -## Provider name (without the `2.dnscrypt.` prefixe) +## Provider name (with or without the `2.dnscrypt-cert.` prefix) provider_name = "secure.dns.test" diff --git a/src/config.rs b/src/config.rs index ad0d83f..8cff57a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -61,8 +61,7 @@ pub struct State { } impl State { - pub fn new(key_cache_capacity: usize) -> Self { - let provider_kp = SignKeyPair::new(); + pub fn with_key_pair(provider_kp: SignKeyPair, key_cache_capacity: usize) -> Self { let dnscrypt_encryption_params_set = vec![DNSCryptEncryptionParams::new( &provider_kp, key_cache_capacity, @@ -73,6 +72,11 @@ impl State { } } + pub fn new(key_cache_capacity: usize) -> Self { + let provider_kp = SignKeyPair::new(); + State::with_key_pair(provider_kp, key_cache_capacity) + } + pub async fn async_save>(&self, path: P) -> Result<(), Error> { let path_tmp = path.as_ref().with_extension("tmp"); let mut fpb = tokio::fs::OpenOptions::new(); diff --git a/src/dnscrypt_certs.rs b/src/dnscrypt_certs.rs index 7136cda..a015d96 100644 --- a/src/dnscrypt_certs.rs +++ b/src/dnscrypt_certs.rs @@ -1,7 +1,6 @@ use crate::config::*; use crate::crypto::*; use crate::dnscrypt::*; -use crate::errors::*; use crate::globals::*; use byteorder::{BigEndian, ByteOrder}; diff --git a/src/main.rs b/src/main.rs index 35b1f15..295a1b0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,5 @@ #![allow(clippy::assertions_on_constants)] -#![allow(unused_imports)] -#![allow(unused_variables)] +#![allow(clippy::type_complexity)] #![allow(dead_code)] #[global_allocator] @@ -47,8 +46,11 @@ use privdrop::PrivDrop; use rand::prelude::*; use std::collections::vec_deque::VecDeque; use std::convert::TryFrom; +use std::fs::File; +use std::io::prelude::*; use std::mem; use std::net::SocketAddr; +use std::path::Path; use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::Arc; use std::time::Duration; @@ -385,19 +387,26 @@ fn main() -> Result<(), Error> { Arg::with_name("config") .long("config") .short("c") - .value_name("FILE") + .value_name("file") .takes_value(true) .default_value("encrypted-dns.toml") .help("Path to the configuration file"), ) + .arg( + Arg::with_name("import-from-dnscrypt-wrapper") + .long("import-from-dnscrypt-wrapper") + .value_name("secret.key file") + .takes_value(true) + .help("Path to the dnscrypt-wrapper secret key"), + ) .get_matches(); let config_path = matches.value_of("config").unwrap(); let config = Config::from_path(config_path)?; let provider_name = match config.dnscrypt.provider_name { - provider_name if provider_name.starts_with("2.dnscrypt.") => provider_name.to_string(), - provider_name => format!("2.dnscrypt.{}", provider_name), + provider_name if provider_name.starts_with("2.dnscrypt-cert.") => provider_name.to_string(), + provider_name => format!("2.dnscrypt-cert.{}", provider_name), }; let external_addr = SocketAddr::new(config.external_addr, 0); @@ -422,6 +431,29 @@ fn main() -> Result<(), Error> { let key_cache_capacity = config.dnscrypt.key_cache_capacity; let state_file = &config.state_file; + + if let Some(secret_key_path) = matches.value_of("import-from-dnscrypt-wrapper") { + let secret_key_path = Path::new(secret_key_path); + warn!("Importing dnscrypt-wrapper key"); + let mut key = vec![]; + File::open(secret_key_path)?.read_to_end(&mut key)?; + if key.len() != 64 { + bail!("Key doesn't have the expected size"); + } + let mut sign_sk_u8 = [0u8; 64]; + let mut sign_pk_u8 = [0u8; 32]; + sign_sk_u8.copy_from_slice(&key); + sign_pk_u8.copy_from_slice(&key[32..]); + let provider_kp = SignKeyPair { + sk: SignSK::from_bytes(sign_sk_u8), + pk: SignPK::from_bytes(sign_pk_u8), + }; + runtime.block_on( + State::with_key_pair(provider_kp, key_cache_capacity).async_save(state_file), + )?; + warn!("Key successfully imported"); + } + let state = match State::from_file(state_file, key_cache_capacity) { Err(_) => { warn!("No state file found... creating a new provider key");