summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLia Lenckowski <lialenck@protonmail.com>2024-08-04 00:20:49 +0200
committerLia Lenckowski <lialenck@protonmail.com>2024-08-04 00:20:49 +0200
commit1932a9c95174d7d211e19203df96a396107373f1 (patch)
treea3cca27f08a1bb5a0d164302e1d76ac16f619708
parent16346472e77565f35e3221b3713ec217f8685b20 (diff)
downloadmaesch-1932a9c95174d7d211e19203df96a396107373f1.tar
maesch-1932a9c95174d7d211e19203df96a396107373f1.tar.bz2
maesch-1932a9c95174d7d211e19203df96a396107373f1.tar.zst
open db, read interfaces, add interfaces
-rw-r--r--Cargo.lock170
-rw-r--r--Cargo.toml1
-rw-r--r--src/daemon.rs143
3 files changed, 312 insertions, 2 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 56e1319..ddc7d53 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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"
diff --git a/Cargo.toml b/Cargo.toml
index e38f5a6..0114aeb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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(())
}