diff options
author | Simon Garrelou <simon@sixfoisneuf.fr> | 2023-04-25 20:50:44 +0200 |
---|---|---|
committer | Simon Garrelou <simon@sixfoisneuf.fr> | 2023-04-25 20:50:44 +0200 |
commit | 946ec2cd916440bf689e79766d9bf12bce0e71fa (patch) | |
tree | 778383b89ab4e837258dd9f6a8d8aadc614d0304 | |
parent | 1b7b415eb9b4b03c976cc2b8d7e63a173e8df502 (diff) | |
download | wgmgr-946ec2cd916440bf689e79766d9bf12bce0e71fa.tar.gz wgmgr-946ec2cd916440bf689e79766d9bf12bce0e71fa.zip |
Use anyhow, +add +config
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Cargo.lock | 7 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/main.rs | 161 | ||||
-rw-r--r-- | src/wg.rs | 3 | ||||
-rw-r--r-- | src/wg/config.rs | 56 | ||||
-rw-r--r-- | src/wg/error.rs | 31 | ||||
-rw-r--r-- | src/wg/peer.rs | 104 |
8 files changed, 297 insertions, 68 deletions
@@ -1 +1,3 @@ | |||
1 | /target | 1 | /target |
2 | private_keys | ||
3 | *.conf \ No newline at end of file | ||
@@ -52,6 +52,12 @@ dependencies = [ | |||
52 | ] | 52 | ] |
53 | 53 | ||
54 | [[package]] | 54 | [[package]] |
55 | name = "anyhow" | ||
56 | version = "1.0.70" | ||
57 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
58 | checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" | ||
59 | |||
60 | [[package]] | ||
55 | name = "bitflags" | 61 | name = "bitflags" |
56 | version = "1.3.2" | 62 | version = "1.3.2" |
57 | source = "registry+https://github.com/rust-lang/crates.io-index" | 63 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -211,6 +217,7 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" | |||
211 | name = "wgmgr" | 217 | name = "wgmgr" |
212 | version = "0.1.0" | 218 | version = "0.1.0" |
213 | dependencies = [ | 219 | dependencies = [ |
220 | "anyhow", | ||
214 | "clap", | 221 | "clap", |
215 | "ipnetwork", | 222 | "ipnetwork", |
216 | ] | 223 | ] |
@@ -6,5 +6,6 @@ edition = "2021" | |||
6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
7 | 7 | ||
8 | [dependencies] | 8 | [dependencies] |
9 | anyhow = "1.0.70" | ||
9 | clap = { version = "4.2.2", features = ["cargo"] } | 10 | clap = { version = "4.2.2", features = ["cargo"] } |
10 | ipnetwork = "0.20.0" | 11 | ipnetwork = "0.20.0" |
diff --git a/src/main.rs b/src/main.rs index 6c4787e..4fdfddd 100644 --- a/src/main.rs +++ b/src/main.rs | |||
@@ -1,19 +1,35 @@ | |||
1 | use std::ffi::OsStr; | ||
2 | use std::fs::{read_to_string, self, File}; | ||
3 | use std::net::Ipv4Addr; | ||
4 | use std::str::FromStr; | ||
1 | use std::{env, process::exit}; | 5 | use std::{env, process::exit}; |
2 | use std::error::Error; | 6 | use std::io::Write; |
3 | 7 | ||
4 | use clap::command; | 8 | use anyhow::{Result, anyhow}; |
9 | use clap::{command, ArgMatches}; | ||
5 | use clap::Command; | 10 | use clap::Command; |
6 | use clap::arg; | 11 | use clap::arg; |
12 | use wg::config::WireguardConfig; | ||
7 | 13 | ||
8 | mod wg; | 14 | mod wg; |
9 | 15 | ||
10 | fn main() { | 16 | fn main() { |
11 | let matches = command!() | 17 | let matches = command!() |
18 | .arg( | ||
19 | arg!( | ||
20 | -c --config <CONFIG> "Configuration file name" | ||
21 | ) | ||
22 | .required(false) | ||
23 | ) | ||
12 | .subcommand_required(true) | 24 | .subcommand_required(true) |
25 | |||
26 | // "ls" | ||
13 | .subcommand( | 27 | .subcommand( |
14 | Command::new("ls") | 28 | Command::new("ls") |
15 | .about("List known clients") | 29 | .about("List known clients") |
16 | ) | 30 | ) |
31 | |||
32 | // "config" | ||
17 | .subcommand( | 33 | .subcommand( |
18 | Command::new("config") | 34 | Command::new("config") |
19 | .about("Generate the configuration file for a client") | 35 | .about("Generate the configuration file for a client") |
@@ -25,14 +41,35 @@ fn main() { | |||
25 | ) | 41 | ) |
26 | .arg(arg!(<PEER> "Name of the peer")) | 42 | .arg(arg!(<PEER> "Name of the peer")) |
27 | ) | 43 | ) |
44 | |||
45 | // "add" | ||
46 | .subcommand( | ||
47 | Command::new("add") | ||
48 | .about("Add a new client to your VPN") | ||
49 | .arg( | ||
50 | arg!( | ||
51 | <NAME> "Name of the new client" | ||
52 | ) | ||
53 | .required(true) | ||
54 | ) | ||
55 | .arg( | ||
56 | arg!( | ||
57 | -i --ip <IP> "IP address (auto-assigned)" | ||
58 | ) | ||
59 | .required(false) | ||
60 | ) | ||
61 | ) | ||
28 | .get_matches(); | 62 | .get_matches(); |
29 | 63 | ||
30 | let conf_path = match env::var("WG_CONF") { | 64 | let conf_path = match find_config_file(&matches) { |
31 | Ok(s) => s, | 65 | Ok(s) => s, |
32 | Err(_) => String::from("/etc/wireguard/wg0.conf") | 66 | Err(e) => { |
67 | eprintln!("Configuration file error: {}", e); | ||
68 | exit(1); | ||
69 | } | ||
33 | }; | 70 | }; |
34 | 71 | ||
35 | let conf = match wg::config::WireguardConfig::new(&conf_path) { | 72 | let mut conf = match wg::config::WireguardConfig::new(&conf_path) { |
36 | Ok(c) => c, | 73 | Ok(c) => c, |
37 | Err(e) => { | 74 | Err(e) => { |
38 | eprintln!("Error loading the configuration file '{}'", conf_path); | 75 | eprintln!("Error loading the configuration file '{}'", conf_path); |
@@ -67,6 +104,17 @@ fn main() { | |||
67 | }, | 104 | }, |
68 | None => {} | 105 | None => {} |
69 | } | 106 | } |
107 | }, | ||
108 | |||
109 | Some(("add", args)) => { | ||
110 | let new_name = args.get_one::<String>("NAME").unwrap().to_string(); | ||
111 | if let Err(e) = do_add(&mut conf, conf_path, &new_name, args.get_one::<String>("ip")) { | ||
112 | eprintln!("Error adding peer: {}", e); | ||
113 | exit(1); | ||
114 | } | ||
115 | else { | ||
116 | println!("Peer '{}' added successfully. Don't forget to restart your WireGuard server.", new_name); | ||
117 | } | ||
70 | } | 118 | } |
71 | 119 | ||
72 | _ => { | 120 | _ => { |
@@ -76,6 +124,63 @@ fn main() { | |||
76 | 124 | ||
77 | } | 125 | } |
78 | 126 | ||
127 | fn find_config_file(matches: &ArgMatches) -> Result<String> { | ||
128 | // Top priority goes to the command-line argument | ||
129 | match matches.get_one::<String>("config") { | ||
130 | Some(s) => { | ||
131 | if s.starts_with("/") { | ||
132 | return Ok(s.to_string()) | ||
133 | } | ||
134 | else { | ||
135 | return Ok(format!("/etc/wireguard/{}", s)) | ||
136 | } | ||
137 | }, | ||
138 | None => {} | ||
139 | } | ||
140 | |||
141 | // Then, if the environment variable exists, we take it | ||
142 | match env::var("WG_CONF") { | ||
143 | Ok(s) => return Ok(s), | ||
144 | Err(_) => {} | ||
145 | }; | ||
146 | |||
147 | // Otherwise, we will first try a simple "wg0.conf" | ||
148 | match read_to_string("/etc/wireguard/wg0.conf") { | ||
149 | Ok(_) => return Ok(String::from_str("/etc/wireguard/wg0.conf").unwrap()), | ||
150 | Err(_) => {} | ||
151 | } | ||
152 | |||
153 | // Finally, we can try to see if there is a single ".conf" file in /etc/wireguard | ||
154 | match fs::read_dir("/etc/wireguard/") { | ||
155 | Ok(d) => { | ||
156 | let conf_files: Vec<fs::DirEntry> = d.filter(|e| { | ||
157 | if let Ok(e) = e { | ||
158 | if e.file_type().unwrap().is_dir() { | ||
159 | return false; | ||
160 | } | ||
161 | |||
162 | match e.path().extension().and_then(OsStr::to_str) { | ||
163 | Some("conf") => { return true} , | ||
164 | _ => {return false}, | ||
165 | } | ||
166 | } | ||
167 | |||
168 | return false; | ||
169 | }).map(|e| { | ||
170 | return e.unwrap(); | ||
171 | }).collect(); | ||
172 | |||
173 | if conf_files.len() == 1 { | ||
174 | return Ok(String::from_str(conf_files[0].path().to_str().unwrap()).unwrap()); | ||
175 | } | ||
176 | else { | ||
177 | return Err(anyhow!("Could not determine the path to your WireGuard configuration file. Set the WG_CONF environment variable, or pass the '--config' parameter.")) | ||
178 | } | ||
179 | }, | ||
180 | Err(e) => return Err(anyhow!("Error listing /etc/wireguard/: {}", e)) | ||
181 | } | ||
182 | } | ||
183 | |||
79 | fn do_list(conf: &wg::config::WireguardConfig) { | 184 | fn do_list(conf: &wg::config::WireguardConfig) { |
80 | let mut max_length = 0; | 185 | let mut max_length = 0; |
81 | for p in conf.peers.iter() { | 186 | for p in conf.peers.iter() { |
@@ -89,30 +194,44 @@ fn do_list(conf: &wg::config::WireguardConfig) { | |||
89 | } | 194 | } |
90 | } | 195 | } |
91 | 196 | ||
92 | fn do_config(conf: &wg::config::WireguardConfig, peer_name: String, is_full: bool) -> Result<(), Box<dyn Error>> { | 197 | fn do_config(conf: &wg::config::WireguardConfig, peer_name: String, is_full: bool) -> Result<()> { |
93 | let peer = match conf.peers.iter().filter(|p| { p.name == peer_name }).nth(0) { | 198 | let peer = match conf.get_peer(peer_name.as_str()) { |
94 | Some(p) => p, | 199 | Some(p) => p, |
95 | None => { | 200 | None => { |
96 | eprintln!("No such peer: {}", peer_name); | 201 | return Err(anyhow!("No such peer: {}", peer_name)); |
97 | exit(1); | ||
98 | } | 202 | } |
99 | }; | 203 | }; |
100 | 204 | ||
101 | println!("[Interface]"); | 205 | println!("{}", peer.gen_config(conf, is_full)?); |
102 | println!("PrivateKey = {}", peer.private_key()?); | ||
103 | println!("Address = {}/32", peer.ip); | ||
104 | println!("DNS = TODO\n"); | ||
105 | 206 | ||
106 | println!("[Peer]"); | 207 | Ok(()) |
107 | println!("PublicKey = TODO"); | 208 | } |
108 | 209 | ||
109 | let allowed_ips = match is_full { | 210 | fn do_add(conf: &mut WireguardConfig, conf_path: String, peer_name: &String, ip: Option<&String>) -> Result<()> { |
110 | true => String::from("0.0.0.0/0"), | 211 | let ip = match ip { |
111 | false => conf.network.to_string() | 212 | Some(s) => { |
213 | Ipv4Addr::from_str(s.as_str())? | ||
214 | }, | ||
215 | None => { | ||
216 | match conf.next_free_ip() { | ||
217 | Ok(i) => i, | ||
218 | Err(e) => { | ||
219 | return Err(e); | ||
220 | } | ||
221 | } | ||
222 | } | ||
112 | }; | 223 | }; |
113 | println!("AllowedIPs = {}", allowed_ips); | 224 | |
114 | println!("Endpoint = TODO"); | 225 | match conf.get_peer(peer_name.as_str()) { |
115 | println!("PersistentKeepAlive = 25"); | 226 | Some(_) => { return Err(anyhow!("There is already a peer named {}", peer_name)); }, |
227 | None => {} | ||
228 | } | ||
229 | |||
230 | let p = wg::peer::Peer::new(peer_name.clone(), ip); | ||
231 | conf.peers.push(p); | ||
232 | |||
233 | let mut f = File::create(conf_path)?; | ||
234 | write!(f, "{}", conf.gen_config()?)?; | ||
116 | 235 | ||
117 | Ok(()) | 236 | Ok(()) |
118 | } \ No newline at end of file | 237 | } \ No newline at end of file |
@@ -1,3 +1,2 @@ | |||
1 | mod error; | ||
2 | pub mod config; | 1 | pub mod config; |
3 | mod peer; \ No newline at end of file | 2 | pub mod peer; \ No newline at end of file |
diff --git a/src/wg/config.rs b/src/wg/config.rs index 03d2ce0..4a07287 100644 --- a/src/wg/config.rs +++ b/src/wg/config.rs | |||
@@ -1,9 +1,10 @@ | |||
1 | use std::str::FromStr; | 1 | use std::str::FromStr; |
2 | use std::{net::Ipv4Addr, fs, error::Error}; | 2 | use std::{net::Ipv4Addr, fs}; |
3 | use std::fmt::Write; | ||
3 | 4 | ||
5 | use anyhow::{Result, anyhow}; | ||
4 | use ipnetwork::Ipv4Network; | 6 | use ipnetwork::Ipv4Network; |
5 | 7 | ||
6 | use crate::wg::error::WgMgrError; | ||
7 | use crate::wg::peer::Peer; | 8 | use crate::wg::peer::Peer; |
8 | 9 | ||
9 | #[derive(Debug)] | 10 | #[derive(Debug)] |
@@ -19,7 +20,7 @@ pub struct WireguardConfig { | |||
19 | 20 | ||
20 | 21 | ||
21 | impl WireguardConfig { | 22 | impl WireguardConfig { |
22 | pub fn new(config_path: &str) -> Result<WireguardConfig, Box<dyn Error>> { | 23 | pub fn new(config_path: &str) -> Result<WireguardConfig> { |
23 | let f = fs::read_to_string(config_path)?; | 24 | let f = fs::read_to_string(config_path)?; |
24 | 25 | ||
25 | let mut conf = WireguardConfig{ | 26 | let mut conf = WireguardConfig{ |
@@ -96,8 +97,7 @@ impl WireguardConfig { | |||
96 | let ip = Ipv4Network::from_str(addr)?; | 97 | let ip = Ipv4Network::from_str(addr)?; |
97 | 98 | ||
98 | if ip.prefix() != 32 { | 99 | if ip.prefix() != 32 { |
99 | let msg = format!("Peer '{}' has invalid net range {}", current_peer.name, ip.prefix()); | 100 | return Err(anyhow!("Peer '{}' has invalid net range {}", current_peer.name, ip.prefix())); |
100 | return Err(Box::new(WgMgrError::new(msg))); | ||
101 | } | 101 | } |
102 | 102 | ||
103 | current_peer.ip = ip.ip(); | 103 | current_peer.ip = ip.ip(); |
@@ -118,7 +118,7 @@ impl WireguardConfig { | |||
118 | } | 118 | } |
119 | 119 | ||
120 | 120 | ||
121 | pub fn next_free_ip(&self) -> Result<Ipv4Addr, WgMgrError> { | 121 | pub fn next_free_ip(&self) -> Result<Ipv4Addr> { |
122 | let mut iter = self.network.iter(); | 122 | let mut iter = self.network.iter(); |
123 | iter.next(); // Skip the first IP (identification) | 123 | iter.next(); // Skip the first IP (identification) |
124 | 124 | ||
@@ -140,19 +140,57 @@ impl WireguardConfig { | |||
140 | } | 140 | } |
141 | } | 141 | } |
142 | 142 | ||
143 | Err(WgMgrError::new(String::from("No more free IP addresses"))) | 143 | Err(anyhow!("No more free IP addresses")) |
144 | } | ||
145 | |||
146 | pub fn get_peer(&self, name: &str) -> Option<&Peer> { | ||
147 | self.peers.iter().filter(|p| { p.name.as_str() == name }).nth(0) | ||
148 | } | ||
149 | |||
150 | pub fn gen_config(&self) -> Result<String, std::fmt::Error> { | ||
151 | let mut res = String::new(); | ||
152 | |||
153 | writeln!(res, "[Interface]")?; | ||
154 | writeln!(res, "PrivateKey = {}", self.private_key)?; | ||
155 | |||
156 | if self.listen_port != 0 { | ||
157 | writeln!(res, "ListenPort = {}", self.listen_port)?; | ||
158 | } | ||
159 | |||
160 | writeln!(res, "Address = {}", self.network)?; | ||
161 | |||
162 | for pre_up in self.pre_ups.iter() { | ||
163 | writeln!(res, "PreUp = {}", pre_up)?; | ||
164 | } | ||
165 | |||
166 | for post_down in self.post_downs.iter() { | ||
167 | writeln!(res, "PostDown = {}", post_down)?; | ||
168 | } | ||
169 | |||
170 | writeln!(res, "")?; | ||
171 | |||
172 | // Now, add each peer | ||
173 | for peer in self.peers.iter() { | ||
174 | writeln!(res, "# {}", peer.name)?; | ||
175 | writeln!(res, "[Peer]")?; | ||
176 | writeln!(res, "PublicKey = {}", peer.public_key)?; | ||
177 | writeln!(res, "AllowedIPs = {}/32", peer.ip)?; | ||
178 | writeln!(res, "")?; | ||
179 | } | ||
180 | |||
181 | Ok(res) | ||
144 | } | 182 | } |
145 | } | 183 | } |
146 | 184 | ||
147 | 185 | ||
148 | 186 | ||
149 | fn config_value(line: &str) -> Result<&str, &str> { | 187 | fn config_value(line: &str) -> Result<&str> { |
150 | match line.find("=") { | 188 | match line.find("=") { |
151 | Some(i) => { | 189 | Some(i) => { |
152 | Ok(line[i+1..].trim()) | 190 | Ok(line[i+1..].trim()) |
153 | }, | 191 | }, |
154 | None => { | 192 | None => { |
155 | Err("line does not seem to contain a key-value pair") | 193 | Err(anyhow!("line does not seem to contain a key-value pair")) |
156 | } | 194 | } |
157 | } | 195 | } |
158 | } \ No newline at end of file | 196 | } \ No newline at end of file |
diff --git a/src/wg/error.rs b/src/wg/error.rs deleted file mode 100644 index 0167b22..0000000 --- a/src/wg/error.rs +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | use std::fmt::{Formatter, Display}; | ||
2 | use std::error::Error; | ||
3 | |||
4 | #[derive(Debug)] | ||
5 | pub struct WgMgrError { | ||
6 | msg: String | ||
7 | } | ||
8 | |||
9 | impl WgMgrError { | ||
10 | pub fn new(msg: String) -> WgMgrError { | ||
11 | WgMgrError { | ||
12 | msg | ||
13 | } | ||
14 | } | ||
15 | } | ||
16 | |||
17 | impl Error for WgMgrError { | ||
18 | fn description(&self) -> &str { | ||
19 | return self.msg.as_str() | ||
20 | } | ||
21 | |||
22 | fn cause(&self) -> Option<&dyn Error> { | ||
23 | None | ||
24 | } | ||
25 | } | ||
26 | |||
27 | impl Display for WgMgrError { | ||
28 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||
29 | write!(f, "{}", self.msg) | ||
30 | } | ||
31 | } \ No newline at end of file | ||
diff --git a/src/wg/peer.rs b/src/wg/peer.rs index 0a25841..17722e5 100644 --- a/src/wg/peer.rs +++ b/src/wg/peer.rs | |||
@@ -1,7 +1,14 @@ | |||
1 | use std::error::Error; | ||
2 | use std::net::Ipv4Addr; | 1 | use std::net::Ipv4Addr; |
3 | use std::env::join_paths; | 2 | use std::env::join_paths; |
4 | use std::fs::read_to_string; | 3 | use std::fs::{read_to_string, self, File}; |
4 | use std::fmt::Write; | ||
5 | use std::path::{Path}; | ||
6 | use std::process::{Command, Stdio}; | ||
7 | use std::io::Write as ioWrite; | ||
8 | |||
9 | use anyhow::Result; | ||
10 | |||
11 | use super::config::WireguardConfig; | ||
5 | 12 | ||
6 | #[derive(Debug)] | 13 | #[derive(Debug)] |
7 | pub struct Peer { | 14 | pub struct Peer { |
@@ -11,16 +18,103 @@ pub struct Peer { | |||
11 | } | 18 | } |
12 | 19 | ||
13 | impl Peer { | 20 | impl Peer { |
14 | pub fn private_key(&self) -> Result<String, Box<dyn Error>> { | 21 | pub fn new(name: String, ip: Ipv4Addr) -> Peer { |
15 | // TODO: do not hardcode where private keys are stored | 22 | let private = Command::new("wg") |
23 | .arg("genkey") | ||
24 | .output() | ||
25 | .expect("Could not generate a private key. Is 'wg' installed?"); | ||
26 | |||
27 | let mut public = Command::new("wg") | ||
28 | .arg("pubkey") | ||
29 | .stdin(Stdio::piped()) | ||
30 | .stdout(Stdio::piped()) | ||
31 | .spawn() | ||
32 | .expect("Could not run 'wg'"); | ||
33 | |||
34 | let private_clone = private.stdout.clone(); | ||
35 | |||
36 | let mut stdin = public.stdin.take().expect("could not open wg stdin"); | ||
37 | std::thread::spawn(move || { | ||
38 | stdin.write_all(&private.stdout).unwrap(); | ||
39 | }); | ||
40 | |||
41 | let output = public.wait_with_output().expect("could not read from 'wg pubkey'"); | ||
42 | |||
43 | let private_key = String::from_utf8(private_clone).expect("could not decode private key"); | ||
44 | let public_key = String::from_utf8(output.stdout).expect("could not decode public key"); | ||
45 | |||
46 | let private_key = private_key.trim(); | ||
47 | let public_key = public_key.trim(); | ||
16 | 48 | ||
49 | let p = Peer{ | ||
50 | name, | ||
51 | ip, | ||
52 | public_key: String::from(public_key) | ||
53 | }; | ||
54 | |||
55 | let mut f = match File::create(p.private_key_path()) { | ||
56 | Ok(f) => f, | ||
57 | Err(e) => { | ||
58 | panic!("Error creating private key file: {}", e); | ||
59 | } | ||
60 | }; | ||
61 | write!(f, "{}", private_key).expect("could not write private key to file"); | ||
62 | |||
63 | p | ||
64 | } | ||
65 | |||
66 | fn private_key_folder(&self) -> String { | ||
17 | let pk_folder = String::from("./private_keys/"); | 67 | let pk_folder = String::from("./private_keys/"); |
18 | let pk_path = join_paths(&[pk_folder, self.name.clone()])?; | ||
19 | 68 | ||
69 | let pk_path = Path::new(pk_folder.as_str()); | ||
70 | if !pk_path.exists() { | ||
71 | fs::create_dir(pk_path).expect("Could not create private keys folder"); | ||
72 | } | ||
73 | |||
74 | if !pk_path.is_dir() { | ||
75 | panic!("Error: the private key folder exists but is not a directory") | ||
76 | } | ||
77 | |||
78 | pk_folder | ||
79 | } | ||
80 | |||
81 | fn private_key_path(&self) -> String { | ||
82 | let folder_name = self.private_key_folder(); | ||
83 | let pk_folder = Path::new(folder_name.as_str()); | ||
84 | let pk_path = pk_folder.join(self.name.clone()); | ||
85 | |||
86 | String::from(pk_path.to_str().unwrap()) | ||
87 | } | ||
88 | |||
89 | pub fn private_key(&self) -> Result<String> { | ||
90 | let pk_folder = self.private_key_folder(); | ||
91 | let pk_path = join_paths(&[pk_folder, self.name.clone()])?; | ||
20 | let pk = read_to_string(pk_path)?; | 92 | let pk = read_to_string(pk_path)?; |
21 | 93 | ||
22 | Ok(pk) | 94 | Ok(pk) |
23 | } | 95 | } |
96 | |||
97 | pub fn gen_config(&self, conf: &WireguardConfig, is_full: bool) -> Result<String>{ | ||
98 | let mut res = String::new(); | ||
99 | |||
100 | writeln!(res, "[Interface]")?; | ||
101 | writeln!(res, "PrivateKey = {}", self.private_key()?)?; | ||
102 | writeln!(res, "Address = {}/32", self.ip)?; | ||
103 | writeln!(res, "DNS = TODO\n")?; | ||
104 | |||
105 | writeln!(res, "[Peer]")?; | ||
106 | writeln!(res, "PublicKey = TODO")?; | ||
107 | |||
108 | let allowed_ips = match is_full { | ||
109 | true => String::from("0.0.0.0/0"), | ||
110 | false => conf.network.to_string() | ||
111 | }; | ||
112 | writeln!(res, "AllowedIPs = {}", allowed_ips)?; | ||
113 | writeln!(res, "Endpoint = TODO")?; | ||
114 | writeln!(res, "PersistentKeepAlive = 25")?; | ||
115 | |||
116 | Ok(res) | ||
117 | } | ||
24 | } | 118 | } |
25 | 119 | ||
26 | impl PartialOrd for Peer { | 120 | impl PartialOrd for Peer { |