summaryrefslogtreecommitdiff
path: root/src/daemon.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon.rs')
-rw-r--r--src/daemon.rs143
1 files changed, 141 insertions, 2 deletions
diff --git a/src/daemon.rs b/src/daemon.rs
index c88912f..2c73d6c 100644
--- a/src/daemon.rs
+++ b/src/daemon.rs
@@ -1,14 +1,153 @@
-use std::net::TcpListener;
+use core::net::SocketAddr;
+use defguard_wireguard_rs::{host::Peer, InterfaceConfiguration, WGApi, WireguardInterfaceApi};
+use defguard_wireguard_rs::{key::Key as WgKey, net::IpAddrMask};
+use log::{info, trace, warn};
+use redb::{Database, Error, Key, Range, ReadableTable, TableDefinition, TypeName, Value};
+use serde::{Deserialize, Serialize};
+use std::net::{TcpListener, ToSocketAddrs};
use thiserror::Error;
+use xdg::BaseDirectories;
+
+use std::str::FromStr;
#[derive(Debug, Error)]
pub enum DaemonError {
#[error("{0}")]
Io(#[from] std::io::Error),
+
+ #[error("{0}")]
+ XdgBase(#[from] xdg::BaseDirectoriesError),
+
+ #[error("{0}")]
+ DbOpen(#[from] redb::DatabaseError),
+ #[error("{0}")]
+ DbTrans(#[from] redb::TransactionError),
+ #[error("{0}")]
+ DbTable(#[from] redb::TableError),
+ #[error("{0}")]
+ DbStorage(#[from] redb::StorageError),
+
+ // TODO hier wärs nett zu unterscheiden was decoded wurde
+ #[error("{0}")]
+ Decoding(#[from] serde_json::Error),
+
+ #[error("{0}")]
+ WgInterfaceError(#[from] defguard_wireguard_rs::error::WireguardInterfaceError),
+}
+
+#[derive(Serialize, Deserialize, Clone)]
+enum Endpoint {
+ Ip(SocketAddr),
+ Domain(String, u16),
}
+// subset of defguard_wireguard_rs::host::Peer, with hostname added
+#[derive(Serialize, Deserialize)]
+struct PeerConfig {
+ pubkey: WgKey,
+ psk: Option<WgKey>,
+ hostname: Option<String>,
+ // if false: the hostname is kept around for sharing, but we personally do not use it
+ use_hostname: bool,
+ endpoint: Option<Endpoint>,
+ ips: Vec<IpAddrMask>,
+}
+
+fn default_wg_port() -> u16 {
+ 51820
+}
+
+#[derive(Serialize, Deserialize)]
+struct InterfaceConfig {
+ privkey: String,
+
+ // this really should be a different type, but this is what defguard takes...
+ address: String,
+
+ #[serde(default = "default_wg_port")]
+ listen_port: u16,
+
+ peers: Vec<PeerConfig>,
+}
+
+// NOTE das ist ne dumme idee gewesen... nen peer hinzufügen braucht jz nen kompletten reserialize
+const NETWORKS: TableDefinition<&str, /* InterfaceConfig */ &[u8]> =
+ TableDefinition::new("networks");
+
pub fn daemon() -> Result<(), DaemonError> {
- let listener = TcpListener::bind("0.0.0.0")?; // TODO
+ let db_path = BaseDirectories::with_prefix("mäsch")?.place_state_file("daemon-db")?;
+ let db = Database::create(db_path)?;
+ info!("opened db");
+
+ let networks: Vec<(String, InterfaceConfig)> = match db.begin_read()?.open_table(NETWORKS) {
+ Err(redb::TableError::TableDoesNotExist(_)) => vec![],
+ Ok(tbl) => tbl
+ .iter()?
+ .map(|kv_result| {
+ let (access_key, access_val) = kv_result?;
+ Ok((
+ access_key.value().to_owned(),
+ serde_json::from_slice(access_val.value())?,
+ ))
+ })
+ .collect::<Result<_, DaemonError>>()?,
+ Err(e) => Err(e)?,
+ };
+
+ //let networks = vec![("kek".to_string(), InterfaceConfig {
+ // privkey: "OK9WQudPVO5rXxcdxdtTzRmJzVu+KuqLMstYsZd8mWE=".to_string(),
+ // address: "1.2.3.4".to_string(),
+ // listen_port: 5221,
+ // peers: vec![PeerConfig {
+ // pubkey: WgKey::from_str("Osrxi/bRVK+FQit7YMbIgSaOWmRDOZQoh/7ddV4eEE8=").unwrap(),
+ // psk: Some(WgKey::from_str("wFiG3II9ivYBn+xjLGChC0PjNlbOibZ1K6pmspPD0Hg=").unwrap()),
+ // hostname: Some("blah.blob".to_string()),
+ // use_hostname: false,
+ // endpoint: Some(Endpoint::Domain("alex.69owo.de".to_string(), 12456)),
+ // ips: vec![IpAddrMask::from_str("5.4.3.2/24").unwrap()],
+ // }],
+ //})];
+
+ // TODO call wg.remove_interface on program exit using a drop impl on an 'Interface' struct
+ // containing the InterfaceConfig and WGApi
+ // TODO possibly add hostnames to /etc/hosts
+ for (name, intr) in networks {
+ let wg = WGApi::new(name.clone(), false)?;
+ let defguard_peers = intr
+ .peers
+ .iter()
+ .map(|p| Peer {
+ public_key: p.pubkey.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.clone(),
+ })
+ .collect();
+ wg.create_interface()?;
+ wg.configure_interface(&InterfaceConfiguration {
+ name,
+ prvkey: intr.privkey,
+ address: intr.address,
+ port: intr.listen_port as u32,
+ peers: defguard_peers,
+ })?;
+ }
Ok(())
}