diff options
author | Lia Lenckowski <lialenck@protonmail.com> | 2024-08-04 00:20:49 +0200 |
---|---|---|
committer | Lia Lenckowski <lialenck@protonmail.com> | 2024-08-04 00:20:49 +0200 |
commit | 1932a9c95174d7d211e19203df96a396107373f1 (patch) | |
tree | a3cca27f08a1bb5a0d164302e1d76ac16f619708 | |
parent | 16346472e77565f35e3221b3713ec217f8685b20 (diff) | |
download | maesch-1932a9c95174d7d211e19203df96a396107373f1.tar maesch-1932a9c95174d7d211e19203df96a396107373f1.tar.bz2 maesch-1932a9c95174d7d211e19203df96a396107373f1.tar.zst |
open db, read interfaces, add interfaces
-rw-r--r-- | Cargo.lock | 170 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/daemon.rs | 143 |
3 files changed, 312 insertions, 2 deletions
@@ -61,6 +61,54 @@ dependencies = [ ] [[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] name = "clap" version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -107,6 +155,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] +name = "defguard_wireguard_rs" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba16f17698d4b389907310af018b0c3a80b025bba9c38d947cbc6dd70921743" +dependencies = [ + "base64", + "libc", + "log", + "netlink-packet-core", + "netlink-packet-generic", + "netlink-packet-route", + "netlink-packet-utils", + "netlink-packet-wireguard", + "netlink-sys", + "nix", + "serde", + "thiserror", +] + +[[package]] name = "env_filter" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -172,10 +240,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] name = "mäsch" version = "0.1.0" dependencies = [ "clap", + "defguard_wireguard_rs", "env_logger", "log", "redb", @@ -186,6 +264,98 @@ dependencies = [ ] [[package]] +name = "netlink-packet-core" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4" +dependencies = [ + "anyhow", + "byteorder", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-generic" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd7eb8ad331c84c6b8cb7f685b448133e5ad82e1ffd5acafac374af4a5a308b" +dependencies = [ + "anyhow", + "byteorder", + "netlink-packet-core", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-route" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053998cea5a306971f88580d0829e90f270f940befd7cf928da179d4187a5a66" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "byteorder", + "libc", + "netlink-packet-core", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-utils" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34" +dependencies = [ + "anyhow", + "byteorder", + "paste", + "thiserror", +] + +[[package]] +name = "netlink-packet-wireguard" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b25b050ff1f6a1e23c6777b72db22790fe5b6b5ccfd3858672587a79876c8f" +dependencies = [ + "anyhow", + "byteorder", + "libc", + "log", + "netlink-packet-generic", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416060d346fbaf1f23f9512963e3e878f1a78e707cb699ba9215761754244307" +dependencies = [ + "bytes", + "libc", + "log", +] + +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] name = "proc-macro2" version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -12,3 +12,4 @@ env_logger = "0" log = "0" thiserror = "1" clap = { version = "4.5.13", features = ["derive"] } +defguard_wireguard_rs = "0" 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(()) } |