diff --git a/Application.Deploy.Dockerfile b/Application.Deploy.Dockerfile
index db11ed1f..3d8dabe5 100644
--- a/Application.Deploy.Dockerfile
+++ b/Application.Deploy.Dockerfile
@@ -3,7 +3,8 @@ RUN apk add -U --no-cache wireguard-tools dumb-init
FROM alpine_wg AS runtime
COPY application/bin/rs-wg /usr/local/cargo/bin/rs-wg
-COPY data/wg /etc/wireguard
+# COPY data/wireguard /etc/wireguard
+CMD [ "mkdir", "/etc/wireguard" ]
COPY data/www /etc/www
WORKDIR /etc/wireguard
EXPOSE 8080
\ No newline at end of file
diff --git a/data/wg0.conf b/data/wg0.conf
index eacfad92..2d546ed4 100644
--- a/data/wg0.conf
+++ b/data/wg0.conf
@@ -3,7 +3,7 @@
# Server
[Interface]
-PrivateKey = aCjYU+CBAkIerzXXFj8hzc4ZmMDLNGrhsxqJjOwtPH0=
+PrivateKey = 7djcxyZBiUQ6OrB36p1cKLGHl1zg5MqQShN9Udl41Hw=
Address = 10.8.0.1/24
ListenPort = 51820
PreUp =
@@ -11,3 +11,9 @@ PostUp = iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE; ip
PreDown =
PostDown =
+# Client: 321 (184a9b70-03b3-4bfb-ae89-ce463634f394)
+[Peer]
+PublicKey = ej10pb+XPRVuotGrkz+423Lku6Jyf5OHqt0ccjx6KU8=
+PresharedKey = Y/5LvXKegqRoeugphZZOLS1/Kl+wN+HdJoCdulxzrEs=
+AllowedIPs = 10.8.0.2/32
+
diff --git a/data/wg0.json b/data/wg0.json
index 1220045d..ca7bbf7f 100644
--- a/data/wg0.json
+++ b/data/wg0.json
@@ -1,8 +1,20 @@
{
"server": {
- "privateKey": "aCjYU+CBAkIerzXXFj8hzc4ZmMDLNGrhsxqJjOwtPH0=",
- "publicKey": "Gi9QI2VgCJK1ziPaE2gE/jXbiXj+Rx3mUbIq8RcHPEE=",
+ "privateKey": "7djcxyZBiUQ6OrB36p1cKLGHl1zg5MqQShN9Udl41Hw=",
+ "publicKey": "kAW7Jefvgqs5H6hyuF05a1vSZJJdAiedg3AnVdgjFVk=",
"address": "10.8.0.1"
},
- "clients": {}
+ "clients": {
+ "184a9b70-03b3-4bfb-ae89-ce463634f394": {
+ "uuid": "184a9b70-03b3-4bfb-ae89-ce463634f394",
+ "name": "321",
+ "address": "10.8.0.2",
+ "privateKey": "+K2Bi7AYB1pUCWqIPdRIpqnGFOjG0PE7W8pOBLsatXo=",
+ "publicKey": "ej10pb+XPRVuotGrkz+423Lku6Jyf5OHqt0ccjx6KU8=",
+ "preSharedKey": "Y/5LvXKegqRoeugphZZOLS1/Kl+wN+HdJoCdulxzrEs=",
+ "createdAt": "2022-12-18T15:55:49Z",
+ "updatedAt": "2022-12-18T15:55:49Z",
+ "enabled": true
+ }
+ }
}
diff --git a/data/www/index.html b/data/www/index.html
index a842588e..e69de29b 100644
--- a/data/www/index.html
+++ b/data/www/index.html
@@ -1,528 +0,0 @@
-
-
-
-
- WireGuard
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Logout
-
-
-
-
- WireGuard
-
-
-
-
-
-
-
There is an update available!
-
{{latestRelease.changelog}}
-
-
-
- Update →
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
![]()
-
-
-
-
-
-
-
-
-
-
-
-
{{client.name}}
-
-
-
$refs['client-' + client.id + '-name'][0].select(), 1);"
- class="cursor-pointer opacity-0 group-hover:opacity-100 transition-opacity">
-
-
-
-
-
-
-
-
-
-
-
-
- {{client.address}}
-
-
- $refs['client-' + client.id + '-address'][0].select(), 1);"
- class="cursor-pointer opacity-0 group-hover:opacity-100 transition-opacity">
-
-
-
-
-
-
- ·
-
- {{client.transferTxCurrent | bytes}}/s
-
-
-
-
- ·
-
- {{client.transferRxCurrent | bytes}}/s
-
-
-
-
- · {{new Date(client.latestHandshakeAt) | timeago}}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
There are no clients yet.
-
-
-
-
-
-
-
-
-
-
-
-
-
![]()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Delete Client
-
-
-
- Are you sure you want to delete {{clientDelete.name}}?
- This action cannot be undone.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Made by Emile Nijssen · Donate · GitHub
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/data/www/manifest.json b/data/www/manifest.json
index 5214f3f3..e69de29b 100644
--- a/data/www/manifest.json
+++ b/data/www/manifest.json
@@ -1,11 +0,0 @@
-{
- "name": "WireGuard",
- "display": "standalone",
- "background_color": "#fff",
- "icons": [
- {
- "src": "img/favicon.png",
- "type": "image/png"
- }
- ]
-}
\ No newline at end of file
diff --git a/docker-compose.deploy.yml b/docker-compose.deploy.yml
index 40325a80..5fef99c9 100644
--- a/docker-compose.deploy.yml
+++ b/docker-compose.deploy.yml
@@ -5,7 +5,7 @@ services:
container_name: rs-wg
environment:
- WIREGUARD_SETTINGS=/etc/wireguard/settings.json
- - WIREGUARD_PATH=/etc/wireguard/
+ - WIREGUARD_PATH=/etc/wireguard
- STATIC_DIR=/etc/www/
- RUST_LOG=actix_web=warn,debug
diff --git a/docker-compose.yml b/docker-compose.yml
index 3d146da0..9f391bee 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -5,7 +5,7 @@ services:
container_name: rs-wg
environment:
- WIREGUARD_SETTINGS=/etc/wireguard/settings.json
- - WIREGUARD_PATH=/etc/wireguard/
+ - WIREGUARD_PATH=/etc/wireguard
- STATIC_DIR=/etc/wireguard/www
- RUST_LOG=actix_web=warn,debug
diff --git a/src/utils/os.rs b/src/utils/os.rs
index 7924e8f8..ac119057 100644
--- a/src/utils/os.rs
+++ b/src/utils/os.rs
@@ -1,8 +1,27 @@
-use std::{ffi::OsStr, string::FromUtf8Error};
+use std::{error::Error, string::FromUtf8Error};
+use futures_util::TryFutureExt;
use log::{info, warn};
use serde::Serialize;
-use tokio::{fs::File, io::AsyncReadExt, process::Command};
+use tokio::{
+ fs::File,
+ io::{AsyncReadExt, AsyncWriteExt},
+ process::Command,
+};
+
+// pub struct Error {
+// error: T,
+// }
+// impl Error {
+// pub fn new(error: T) -> Self {
+// Self { error }
+// }
+// }
+// impl ToString for Error {
+// fn to_string(&self) -> String {
+// self.error.to_string()
+// }
+// }
#[derive(Serialize)]
pub struct StdResult {
@@ -21,26 +40,38 @@ impl StdResult {
}
}
-pub async fn load_file>(path: S) -> Result {
+pub async fn write_file, D: Into>(
+ path: P,
+ data: D,
+) -> Result<(), std::io::Error> {
tokio::fs::OpenOptions::new()
- .append(false)
- .read(true)
- .write(true)
.create(true)
+ .write(true)
+ .truncate(true)
.open(path.into())
+ .and_then(|mut file| async move { file.write(data.into().as_bytes()).await.map(|_| file) })
+ .and_then(|mut file| async move { file.flush().await })
.await
}
-pub async fn read_file(mut file: File) -> Result {
- let mut dst = String::new();
- file.read_to_string(&mut dst).await.map(|_| dst)
+pub async fn read_file>(path: S) -> Result {
+ tokio::fs::OpenOptions::new()
+ .create(true)
+ .write(true)
+ .read(true)
+ .open(path.into())
+ .and_then(|mut file| async move {
+ let mut dst = String::new();
+ file.read_to_string(&mut dst).await.map(|_| dst)
+ })
+ .await
}
pub async fn load_file_unhandled(path: &str) -> File {
match tokio::fs::OpenOptions::new()
- .append(false)
.read(true)
.write(true)
+ .truncate(true)
.create(true)
.open(path)
.await
@@ -65,27 +96,23 @@ pub async fn load_and_read_file_unhandled(path: &str) -> (File, String) {
}
}
-pub async fn exec_sh>(command: S) -> Result {
- let command = command.into();
+pub async fn exec_sh(command: &S) -> Result> {
+ let command = command.to_string();
info!("$ {}", command.clone());
let res = match Command::new("sh").arg("-c").arg(command).output().await {
Ok(val) => val,
- Err(err) => return Err(err.to_string()),
+ Err(err) => return Err(Box::new(err)),
};
let stdout_b = &res.stdout.to_vec();
let stderr_b = &res.stderr.to_vec();
- let stdout = match remove_escape(stdout_b) {
- Ok(val) => val,
- Err(err) => return Err(err.to_string()),
- };
- let stderr = match remove_escape(stderr_b) {
- Ok(val) => val,
- Err(err) => return Err(err.to_string()),
- };
-
- Ok(StdResult { stdout, stderr })
+ match remove_escape(stdout_b)
+ .and_then(|stdout| remove_escape(stderr_b).map(|stderr| (stdout, stderr)))
+ {
+ Ok((stdout, stderr)) => Ok(StdResult { stdout, stderr }),
+ Err(err) => return Err(Box::new(err)),
+ }
}
pub fn remove_escape(bytes: &Vec) -> Result {
diff --git a/src/wg_rs/config.rs b/src/wg_rs/config.rs
index 5dafb6b4..b57c74a2 100644
--- a/src/wg_rs/config.rs
+++ b/src/wg_rs/config.rs
@@ -1,11 +1,12 @@
-use std::{collections::HashMap, sync::Arc};
+use std::{collections::HashMap, error::Error, sync::Arc};
use chrono::{SecondsFormat, SubsecRound, Utc};
use futures_util::TryFutureExt;
+use log::error;
use serde::{Deserialize, Serialize};
-use tokio::{io::AsyncWriteExt, join};
+use tokio::join;
use uuid::Uuid;
use crate::utils::{misc, os};
@@ -127,38 +128,45 @@ pub struct Accessor {
}
impl Accessor {
- pub async fn new(memento_path: String, config_path: String, settings: Arc) -> Self {
- let memento_str = os::load_file(memento_path.clone())
- .and_then(|file| os::read_file(file))
+ pub async fn build(
+ memento_path: String,
+ config_path: String,
+ settings: Arc,
+ ) -> Result> {
+ let memento_str = os::read_file(memento_path.clone())
.await
.expect("Could not read memento");
- let memento = if memento_str.is_empty() {
+ if memento_str.is_empty() {
log::info!("Creating new WireGuard configuration...");
- let private_key = os::exec_sh("wg genkey").await.expect("error genkey").stdout;
- let public_key = os::exec_sh(format!("echo {} | wg pubkey", private_key))
+ os::exec_sh(&"wg genkey")
+ .and_then(|res_public| async move {
+ os::exec_sh(&format!("echo {} | wg pubkey", &res_public.stdout))
+ .await
+ .map(|res_private| (res_public.stdout, res_private.stdout))
+ })
.await
- .expect("error pubkey")
- .stdout;
-
- let address = settings.default_address.clone();
- let memento = Memento::new(Server {
- private_key,
- public_key,
- address,
- });
- log::info!("WireGuard configuration generated...");
- memento
+ .and_then(|(public_key, private_key)| {
+ let address = settings.default_address.clone();
+ let memento = Memento::new(Server {
+ private_key,
+ public_key,
+ address,
+ });
+ log::info!("WireGuard configuration generated...");
+ Ok(memento)
+ })
} else {
- serde_json::from_str(&memento_str).expect("Could not serialize memento")
- };
-
- Self {
- config_path,
- memento_path,
- memento,
- settings,
+ Ok(serde_json::from_str(&memento_str).expect("Could not serialize memento"))
}
+ .and_then(|memento| {
+ Ok(Self {
+ config_path,
+ memento_path,
+ memento,
+ settings,
+ })
+ })
}
pub async fn set(&mut self, memento: Memento) {
@@ -169,25 +177,20 @@ impl Accessor {
ser_memento.push('\n');
ser_config.push('\n');
- _ = join!(
- async {
- let mut file = os::load_file(self.memento_path.clone())
- .await
- .expect("Could not load memento");
- file.write(ser_memento.as_bytes())
- .await
- .expect("Could not write memento");
- },
- async {
- let mut file = os::load_file(self.config_path.clone())
- .await
- .expect("Could not load config");
- file.write(ser_config.as_bytes())
- .await
- .expect("Could not write config");
- }
+ let (memento_wr, config_wr) = join!(
+ os::write_file(self.memento_path.clone(), ser_memento),
+ os::write_file(self.config_path.clone(), ser_config)
);
+ memento_wr.unwrap_or_else(|err| {
+ error!("Could not write memento: {}", err);
+ panic!()
+ });
+ config_wr.unwrap_or_else(|err| {
+ error!("Could not write config: {}", err);
+ panic!()
+ });
+
self.memento = memento;
}
diff --git a/src/wg_rs/wireguard.rs b/src/wg_rs/wireguard.rs
index f7770c43..eac22f42 100644
--- a/src/wg_rs/wireguard.rs
+++ b/src/wg_rs/wireguard.rs
@@ -2,6 +2,7 @@ use std::sync::Arc;
use chrono::{SecondsFormat, SubsecRound, Utc};
+use log::error;
use uuid::Uuid;
use crate::utils::{misc, os};
@@ -17,7 +18,7 @@ pub struct WireGuard {
impl WireGuard {
pub async fn new(name: &str, wg_path: String, settings: Settings) -> Self {
- let path = format!("{}{}", wg_path, name);
+ let path = format!("{}/{}", wg_path, name);
let config_path = format!("{}.conf", path);
let memento_path = format!("{}.json", path);
let name = format!("{}", name);
@@ -27,32 +28,46 @@ impl WireGuard {
Self {
name,
settings: counter.clone(),
- memento_accessor: Accessor::new(memento_path, config_path, counter).await,
+ memento_accessor: Accessor::build(memento_path, config_path, counter)
+ .await
+ .unwrap_or_else(|err| {
+ error!("Error initializing Wireguard: {}", err);
+ panic!()
+ }),
}
}
pub async fn quick_up(&self) {
- let result = os::exec_sh(format!("wg-quick up {}", &self.name))
+ os::exec_sh(&format!("wg-quick up {}", &self.name))
.await
- .expect("Error");
- result.log();
+ .unwrap_or_else(|err| {
+ error!("Error quick_up: {}", err);
+ panic!()
+ })
+ .log();
}
pub async fn quick_down(&self) {
- let result = os::exec_sh(format!("wg-quick down {}", &self.name))
+ os::exec_sh(&format!("wg-quick down {}", &self.name))
.await
- .expect("Error");
- result.log();
+ .unwrap_or_else(|err| {
+ error!("Error quick_down: {}", err);
+ panic!()
+ })
+ .log();
}
pub async fn sync_config(&self) {
- let result = os::exec_sh(format!(
+ os::exec_sh(&format!(
"wg syncconf {} <(wg-quick strip {})",
self.name, self.name
))
.await
- .expect("Error syncing");
- result.log();
+ .unwrap_or_else(|err| {
+ error!("Error syncing: {}", err);
+ panic!()
+ })
+ .log();
}
pub async fn start(&mut self) {
@@ -64,12 +79,18 @@ impl WireGuard {
}
pub async fn create_client(&mut self, name: String) -> Client {
- let private_key = os::exec_sh("wg genkey").await.expect("error genkey").stdout;
+ let private_key = os::exec_sh(&"wg genkey")
+ .await
+ .expect("error genkey")
+ .stdout;
let pub_cmd = format!("echo {} | wg pubkey", private_key);
- let public_key = os::exec_sh(pub_cmd).await.expect("error pubkey").stdout;
+ let public_key = os::exec_sh(&pub_cmd).await.expect("error pubkey").stdout;
- let pre_shared_key = os::exec_sh("wg genpsk").await.expect("error genpsk").stdout;
+ let pre_shared_key = os::exec_sh(&"wg genpsk")
+ .await
+ .expect("error genpsk")
+ .stdout;
let mut memento = self.memento_accessor.get();
@@ -122,7 +143,7 @@ impl WireGuard {
}
pub async fn get_clients(&self) -> Vec {
- let res = os::exec_sh("wg show wg0 dump").await.unwrap();
+ let res = os::exec_sh(&"wg show wg0 dump").await.unwrap();
let lines: Vec> = res
.stdout