summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLia Lenckowski <lialenck@protonmail.com>2024-08-10 00:46:45 +0200
committerLia Lenckowski <lialenck@protonmail.com>2024-08-10 00:46:45 +0200
commitc5ae944b3d0442cf8c0015d42e32c1ceea8d1c20 (patch)
tree30f2b29dbbb4f3d1b7829b5d2236ce09caa84305
parent1932a9c95174d7d211e19203df96a396107373f1 (diff)
downloadmaesch-c5ae944b3d0442cf8c0015d42e32c1ceea8d1c20.tar
maesch-c5ae944b3d0442cf8c0015d42e32c1ceea8d1c20.tar.bz2
maesch-c5ae944b3d0442cf8c0015d42e32c1ceea8d1c20.tar.zst
impl hostname ding; remove redb (deemed inefficient overkill)
we are not planning to be web-scale(tm) anyway
-rw-r--r--Cargo.lock106
-rw-r--r--Cargo.toml12
-rw-r--r--src/daemon.rs158
-rw-r--r--src/main.rs2
4 files changed, 211 insertions, 67 deletions
diff --git a/Cargo.lock b/Cargo.lock
index ddc7d53..f3be1b1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -67,6 +67,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
+name = "atomic-write-file"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cbf54d4588732bdfc5ebc3eb9f74f20e027112fc31de412fc7ff0cd1c6896dae"
+dependencies = [
+ "nix 0.28.0",
+ "rand",
+]
+
+[[package]]
name = "autocfg"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -109,6 +119,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
+name = "cfg_aliases"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
+
+[[package]]
name = "clap"
version = "4.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -169,7 +185,7 @@ dependencies = [
"netlink-packet-utils",
"netlink-packet-wireguard",
"netlink-sys",
- "nix",
+ "nix 0.27.1",
"serde",
"thiserror",
]
@@ -198,6 +214,17 @@ dependencies = [
]
[[package]]
+name = "getrandom"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -252,11 +279,11 @@ dependencies = [
name = "mäsch"
version = "0.1.0"
dependencies = [
+ "atomic-write-file",
"clap",
"defguard_wireguard_rs",
"env_logger",
"log",
- "redb",
"serde",
"serde_json",
"thiserror",
@@ -350,12 +377,33 @@ dependencies = [
]
[[package]]
+name = "nix"
+version = "0.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
+dependencies = [
+ "bitflags 2.6.0",
+ "cfg-if",
+ "cfg_aliases",
+ "libc",
+]
+
+[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
+name = "ppv-lite86"
+version = "0.2.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
name = "proc-macro2"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -374,12 +422,33 @@ dependencies = [
]
[[package]]
-name = "redb"
-version = "2.1.1"
+name = "rand"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6dd20d3cdeb9c7d2366a0b16b93b35b75aec15309fbeb7ce477138c9f68c8c0"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
]
[[package]]
@@ -499,6 +568,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -576,3 +651,24 @@ name = "xdg"
version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546"
+
+[[package]]
+name = "zerocopy"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+dependencies = [
+ "byteorder",
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/Cargo.toml b/Cargo.toml
index 0114aeb..7cb0994 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,12 +4,12 @@ version = "0.1.0"
edition = "2021"
[dependencies]
-redb = "2"
-serde = { version = "1", features = ["derive"] }
-serde_json = "1"
-xdg = "2"
+atomic-write-file = "0"
+clap = { version = "4.5.13", features = ["derive"] }
+defguard_wireguard_rs = "0"
env_logger = "0"
log = "0"
+serde_json = "1"
+serde = { version = "1", features = ["derive"] }
thiserror = "1"
-clap = { version = "4.5.13", features = ["derive"] }
-defguard_wireguard_rs = "0"
+xdg = "2"
diff --git a/src/daemon.rs b/src/daemon.rs
index 2c73d6c..1c746fd 100644
--- a/src/daemon.rs
+++ b/src/daemon.rs
@@ -1,9 +1,12 @@
+use atomic_write_file::AtomicWriteFile;
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 defguard_wireguard_rs::{key::Key, net::IpAddrMask};
+use log::{info, warn};
use serde::{Deserialize, Serialize};
+use std::collections::BTreeSet;
+use std::fs::File;
+use std::io::{ErrorKind, Read, Write};
use std::net::{TcpListener, ToSocketAddrs};
use thiserror::Error;
use xdg::BaseDirectories;
@@ -18,15 +21,6 @@ pub enum DaemonError {
#[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),
@@ -44,13 +38,12 @@ enum Endpoint {
// 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,
+ pubkey: Key,
+ psk: Option<Key>,
+ 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>,
- ips: Vec<IpAddrMask>,
}
fn default_wg_port() -> u16 {
@@ -58,7 +51,8 @@ fn default_wg_port() -> u16 {
}
#[derive(Serialize, Deserialize)]
-struct InterfaceConfig {
+struct Network {
+ name: String,
privkey: String,
// this really should be a different type, but this is what defguard takes...
@@ -70,50 +64,66 @@ struct InterfaceConfig {
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");
+#[derive(Serialize, Deserialize, Default)]
+struct Config {
+ networks: Vec<Network>,
+}
pub fn daemon() -> Result<(), DaemonError> {
- 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 config_path = BaseDirectories::with_prefix("mäsch")?.place_state_file("daemon.json")?;
+ let config: Config = match File::open(config_path) {
+ Ok(f) => serde_json::from_reader(f)?,
+ Err(e) => match e.kind() {
+ ErrorKind::NotFound => Config::default(),
+ _ => Err(e)?,
+ },
};
+ info!("read config");
- //let networks = vec![("kek".to_string(), InterfaceConfig {
+ //let networks = vec![Network {
+ // name: "kek".to_string(),
// 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,
+ // pubkey: Key::from_str("Osrxi/bRVK+FQit7YMbIgSaOWmRDOZQoh/7ddV4eEE8=").unwrap(),
+ // psk: Some(Key::from_str("wFiG3II9ivYBn+xjLGChC0PjNlbOibZ1K6pmspPD0Hg=").unwrap()),
+ // use_hostnames: true,
// endpoint: Some(Endpoint::Domain("alex.69owo.de".to_string(), 12456)),
- // ips: vec![IpAddrMask::from_str("5.4.3.2/24").unwrap()],
+ // ips: vec![(IpAddrMask::from_str("5.4.3.2/24").unwrap(), Some("blah.blub".to_owned()))],
// }],
- //})];
+ //}];
// 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
+ // containing the Network and WGApi
+
+ let mut hostfile = match File::open("/etc/hosts") {
+ Ok(mut f) => {
+ let mut r = String::new();
+ f.read_to_string(&mut r)?;
+
+ let seen_hostnames: BTreeSet<String> = r
+ .lines()
+ .map(|l| {
+ l.split_whitespace()
+ .take_while(|dom| dom.chars().next().unwrap() != '#')
+ .skip(1)
+ })
+ .flatten()
+ .map(|dom| dom.to_owned())
+ .collect();
+
+ Some((r, seen_hostnames))
+ }
+ Err(e) => {
+ warn!("failed to read /etc/hosts: {e}");
+ None
+ }
+ };
+
+ for nw in config.networks {
+ let wg = WGApi::new(nw.name.clone(), false)?;
+ let defguard_peers = nw
.peers
.iter()
.map(|p| Peer {
@@ -136,18 +146,54 @@ pub fn daemon() -> Result<(), DaemonError> {
tx_bytes: 0,
rx_bytes: 0,
persistent_keepalive_interval: None,
- allowed_ips: p.ips.clone(),
+ allowed_ips: p.ips.iter().map(|(ip_mask, _)| ip_mask.clone()).collect(),
})
.collect();
wg.create_interface()?;
wg.configure_interface(&InterfaceConfiguration {
- name,
- prvkey: intr.privkey,
- address: intr.address,
- port: intr.listen_port as u32,
+ name: nw.name.clone(),
+ prvkey: nw.privkey,
+ address: nw.address,
+ port: nw.listen_port as u32,
peers: defguard_peers,
})?;
+
+ if let Some((hosts_str, hosts)) = &mut hostfile {
+ nw.peers
+ .iter()
+ .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();
+ }
+
+ info!("loaded configuration for {0}", nw.name);
}
+ info!("loaded all existing configurations");
+
+ if let Some((hosts_str, _)) = &hostfile {
+ info!("proposed next hosts file: {hosts_str}");
+
+ let mut f = AtomicWriteFile::open("/etc/hosts")?;
+ f.write(hosts_str.as_bytes())?;
+ f.commit();
+ }
+
+ // TODO open dbus & network interfaces
Ok(())
}
diff --git a/src/main.rs b/src/main.rs
index 6bc049b..d85da33 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,5 @@
+#![feature(let_chains)]
+
pub mod daemon;
use clap::{Parser, Subcommand};