summaryrefslogtreecommitdiff
path: root/src/daemon.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon.rs')
-rw-r--r--src/daemon.rs214
1 files changed, 24 insertions, 190 deletions
diff --git a/src/daemon.rs b/src/daemon.rs
index b5d1fc4..bf6105c 100644
--- a/src/daemon.rs
+++ b/src/daemon.rs
@@ -1,5 +1,3 @@
-use atomic_write_file::AtomicWriteFile;
-use base64::prelude::*;
use core::net::SocketAddr;
use dbus::{channel::MatchingReceiver, message::MatchRule};
use dbus_crossroads::{Context, Crossroads, MethodErr};
@@ -7,7 +5,6 @@ use defguard_wireguard_rs::{
host::Peer, key::Key, net::IpAddrMask, InterfaceConfiguration, WGApi, WireguardInterfaceApi,
};
use log::{debug, error, info, warn};
-use rand::Rng;
use serde::{Deserialize, Serialize};
use std::{
collections::{BTreeSet, HashMap},
@@ -16,6 +13,7 @@ use std::{
marker::PhantomData,
net::ToSocketAddrs,
ops::DerefMut,
+ str::FromStr,
sync::Arc,
time::SystemTime,
};
@@ -29,7 +27,7 @@ use tokio::{
};
use xdg::BaseDirectories;
-use std::str::FromStr;
+use crate::{daemon_dbus::*, daemon_network::*};
#[derive(Debug, Error)]
pub enum DaemonError {
@@ -54,24 +52,24 @@ pub enum DaemonError {
}
#[derive(Serialize, Deserialize, Clone)]
-enum Endpoint {
+pub enum Endpoint {
Ip(SocketAddr),
Domain(String, u16),
}
// subset of defguard_wireguard_rs::host::Peer, with hostname added
#[derive(Serialize, Deserialize)]
-struct PeerConfig {
- psk: Option<Key>,
- ips: Vec<(IpAddrMask, Option<String>)>,
+pub struct PeerConfig {
+ pub psk: Option<Key>,
+ pub ips: Vec<(IpAddrMask, Option<String>)>,
// if false: the hostnames are kept around for sharing, but we personally do not use them
- use_hostnames: bool,
- endpoint: Option<Endpoint>,
+ pub use_hostnames: bool,
+ pub endpoint: Option<Endpoint>,
- last_changed: SystemTime,
- known_to: Vec<usize>,
+ pub last_changed: SystemTime,
+ pub known_to: Vec<usize>,
- mäsch_endpoint: SocketAddr,
+ pub mäsch_endpoint: SocketAddr,
}
fn default_wg_port() -> u16 {
@@ -79,30 +77,27 @@ fn default_wg_port() -> u16 {
}
#[derive(Serialize, Deserialize)]
-struct Network {
- privkey: String,
-
+pub struct Network {
+ pub privkey: String,
// this really should be a different type, but this is what defguard takes...
- address: String,
-
+ pub address: String,
#[serde(default = "default_wg_port")]
- listen_port: u16,
-
- peers: HashMap<Key, PeerConfig>,
+ pub listen_port: u16,
+ pub peers: HashMap<Key, PeerConfig>,
- mäsch_port: u16,
+ pub mäsch_port: u16,
}
#[derive(Serialize, Deserialize, Default)]
-struct Config {
- networks: HashMap<String, Network>,
+pub struct Config {
+ pub networks: HashMap<String, Network>,
}
// TODO das überschreibt änderungen an /etc/hosts während der runtime :(
-struct State {
- conf: Config,
- nw_handles: HashMap<String, (WGApi, task::JoinHandle<()>)>,
- hostfile: Option<(String, BTreeSet<String>)>,
+pub struct State {
+ pub conf: Config,
+ pub nw_handles: HashMap<String, (WGApi, task::JoinHandle<()>)>,
+ pub hostfile: Option<(String, BTreeSet<String>)>,
}
impl Drop for State {
@@ -250,160 +245,7 @@ async fn run_networks(state: Arc<RwLock<State>>) -> Result<(), DaemonError> {
Ok(())
}
-// TODO also take peers
-async fn handle_add_network(
- mut ctx: Context,
- state: Arc<RwLock<State>>,
- (name, may_key, may_ip, may_lp, may_mp): (String, String, String, u16, u16),
-) -> PhantomData<(bool,)> {
- // NOTE: this is kinda stupid: we convert to a string later anyways, as thats what
- // defguard_wg takes...
- let key = Key::new(match may_key.as_str() {
- "" => rand::thread_rng().gen(),
- _ => match BASE64_STANDARD.decode(may_key) {
- Ok(v) if v.len() == 32 => v.try_into().unwrap(),
- _ => {
- warn!("AddNetwork with bad key");
- return ctx.reply(Err(MethodErr::invalid_arg("bad key")));
- }
- },
- });
-
- // we store the ip as the original string, but should validate it regardless
- let (ip, ip_string) = match may_ip.as_str() {
- "" => todo!(),
- _ => match IpAddrMask::from_str(&may_ip) {
- Ok(ip_mask) => (ip_mask.ip, may_ip),
- Err(_) => {
- warn!("AddNetwork with bad ip");
- return ctx.reply(Err(MethodErr::invalid_arg("invalid ip")));
- }
- },
- };
-
- let lp = if may_lp == 0 { 25565 } else { may_lp };
- let mp = if may_mp == 0 { 51820 } else { may_mp };
-
- let mut state_rw_guard = state.write().await;
- let state_rw = state_rw_guard.deref_mut();
-
- let wg_api = match add_network(
- &mut state_rw.hostfile,
- name.clone(),
- key.to_string(),
- ip_string,
- lp,
- &HashMap::new(),
- )
- .await
- {
- Ok(wg_api) => wg_api,
- Err(e) => {
- warn!("AddNetwork couldn't add network: {e}");
- return ctx.reply(Err(MethodErr::failed(&e)));
- }
- };
-
- // TODO ins wg_api
- let listener = match TcpListener::bind((ip, mp)).await {
- Ok(l) => l,
- Err(e) => {
- let _ = wg_api.remove_interface();
- warn!("AddNetwork couldn't start listener: {e}");
- return ctx.reply(Err(MethodErr::failed(&e)));
- }
- };
- let h = task::spawn(print_error(run_network(
- state.clone(),
- listener,
- name.clone(),
- )));
-
- state_rw.nw_handles.insert(name.clone(), (wg_api, h));
-
- // TODO save new config
-
- ctx.reply(Ok((true,)))
-}
-
-async fn add_network(
- hostfile: &mut Option<(String, BTreeSet<String>)>,
- name: String,
- privkey: String,
- address: String,
- port: u16,
- peers: &HashMap<Key, PeerConfig>,
-) -> Result<WGApi, DaemonError> {
- let wg = WGApi::new(name.clone(), false)?;
- let defguard_peers = peers
- .iter()
- .map(|(peer_key, p)| Peer {
- public_key: peer_key.clone(),
- preshared_key: p.psk.clone(),
- protocol_version: None,
- endpoint: p
- .endpoint
- .clone()
- .map(|e| match e {
- Endpoint::Ip(ep) => Some(ep),
- Endpoint::Domain(s, p) => (s, p)
- .to_socket_addrs()
- .ok()
- .map(|mut it| it.next())
- .flatten(),
- })
- .flatten(),
- last_handshake: None,
- tx_bytes: 0,
- rx_bytes: 0,
- persistent_keepalive_interval: None,
- allowed_ips: p.ips.iter().map(|(ip_mask, _)| ip_mask.clone()).collect(),
- })
- .collect();
- wg.create_interface()?;
- wg.configure_interface(&InterfaceConfiguration {
- name: name.clone(),
- prvkey: privkey,
- address: address,
- port: port as u32,
- peers: defguard_peers,
- })?;
-
- if let Some((hosts_str, hosts)) = hostfile {
- peers
- .values()
- .map(|peer| {
- if peer.use_hostnames {
- peer.ips
- .iter()
- .map(|(mask, may_dom)| {
- if let Some(dom) = may_dom
- && hosts.insert(dom.clone())
- {
- hosts_str.push_str(&format!("{}", mask.ip));
- hosts_str.push('\t');
- hosts_str.push_str(&dom);
- hosts_str.push('\n');
- }
- })
- .count();
- }
- })
- .count();
- }
-
- if let Some((hosts_str, _)) = hostfile {
- debug!("writing hosts file: {hosts_str}");
-
- let mut f = AtomicWriteFile::open("/etc/hosts")?;
- f.write(hosts_str.as_bytes())?;
- f.commit()?;
- }
-
- Ok(wg)
-}
-
-async fn print_error<E: std::fmt::Display, O, F: std::future::Future<Output = Result<O, E>>>(
+pub async fn print_error<E: std::fmt::Display, O, F: std::future::Future<Output = Result<O, E>>>(
f: F,
) -> () {
match f.await {
@@ -411,11 +253,3 @@ async fn print_error<E: std::fmt::Display, O, F: std::future::Future<Output = Re
_ => (),
};
}
-
-async fn run_network(
- state: Arc<RwLock<State>>,
- sock: TcpListener,
- nw_name: String,
-) -> Result<(), DaemonError> {
- Ok(())
-}