Skip to content

Commit a08e209

Browse files
authored
support multiple network: stage 2 (#34)
1 parent 4ff95e0 commit a08e209

File tree

10 files changed

+79
-39
lines changed

10 files changed

+79
-39
lines changed

admin-web/src/view/node/NodeDetailPage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ export function RelayConfigView({hide}: {hide:boolean}) {
1212
const postUpTooltip =(
1313
<>
1414
<p>This command run after node up, it normally used for config os to allow ForNet redirect network packages. The command would be:</p>
15-
<p style={{fontStyle:'italic'}}>iptables -A FORWARD -i for0 -j ACCEPT; iptables -A FORWARD -o for0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE</p>
15+
<p style={{fontStyle:'italic'}} dangerouslySetInnerHTML={{__html:'iptables -A FORWARD -i {tun} -j ACCEPT; iptables -A FORWARD -o {tun} -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE'}}></p>
1616
<p>(Please remember to change <span style={{fontWeight:'bold'}}>eth0</span> to correct ethernet interface)</p>
1717
</>
1818
)
1919
const postDownToolTip = (
2020
<>
2121
<p>This command run after node down, it normally used for config OS to remove ForNet postUp command effects. The command would be:</p>
22-
<p style={{fontStyle:'italic'}}>iptables -D FORWARD -i for0 -j ACCEPT; iptables -D FORWARD -o for0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE</p>
22+
<p style={{fontStyle:'italic'}} dangerouslySetInnerHTML={{__html: 'iptables -D FORWARD -i {tun} -j ACCEPT; iptables -D FORWARD -o {tun} -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE'}}></p>
2323
<p>(Please remember to change <span style={{fontWeight:'bold'}}>eth0</span> to correct ethernet interface)</p>
2424

2525
</>

client/Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/lib/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ serde = { version = "1.0.144", features = ["derive"] }
3636
serde_derive = "1.0.144"
3737
serde_json = "1.0.85"
3838
reqwest = { version = "0.11", features = ["json", "blocking"]}
39+
new_string_template = "1.4.0"
3940

4041
dirs = "4.0.0"
4142

client/lib/src/api/mod.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,8 @@ pub async fn api_handler(server_manager: &mut ServerManager, command: String, st
156156
}
157157
}
158158
"list" => {
159-
if server_manager.wr_manager.is_alive() {
160-
let data = server_manager.wr_manager.device_info();
161-
let _ = stream.write(ApiResponse::boxed(data).to_json().as_bytes()).await;
162-
}
159+
let data = server_manager.wr_manager.device_info();
160+
let _ = stream.write(ApiResponse::boxed(data).to_json().as_bytes()).await;
163161
}
164162
"autoLaunch" => {
165163
cfg_if! {

client/lib/src/device/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use allowed_ips::AllowedIps;
4040
use peer::{AllowedIP, Peer};
4141
use script_run::Scripts;
4242
use crate::device::peer::TcpConnection;
43-
use crate::device::script_run::run_opt_script;
43+
use crate::device::script_run::{run_opt_script, run_opt_script_with_param};
4444
use crate::protobuf::config::NodeType;
4545
use self::tun::WritePart;
4646

@@ -232,7 +232,9 @@ impl DeviceData {
232232

233233
impl Drop for DeviceData {
234234
fn drop(&mut self) {
235-
let _ = run_opt_script(&self.scripts.post_down);
235+
let mut script_param:HashMap<&str, String> = HashMap::new();
236+
script_param.insert("tun", self.name.clone());
237+
let _ = run_opt_script_with_param(&self.scripts.post_down , &script_param);
236238
}
237239
}
238240

client/lib/src/device/script_run.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::collections::HashMap;
2+
use new_string_template::template::Template;
13
use shell_candy::{ShellTask, ShellTaskBehavior, ShellTaskLog};
24
use crate::protobuf::config::Interface;
35

@@ -19,6 +21,22 @@ impl Scripts {
1921
}
2022
}
2123
}
24+
pub fn run_opt_script_with_param(script:&Option<String>, params:&HashMap<&str,String>) -> shell_candy::Result<Option<()>> {
25+
if let Some(ref script) = script {
26+
let templ = Template::new(script);
27+
match templ.render(params) {
28+
Ok(rendered_script) => {
29+
Ok(Some(run_script(&rendered_script)?))
30+
}
31+
Err(e) => {
32+
tracing::warn!("script: {script} render err: {e}");
33+
Ok(None)
34+
}
35+
}
36+
} else {
37+
Ok(None)
38+
}
39+
}
2240
//TODO: add log and handle if this would block.
2341
pub fn run_opt_script(script:&Option<String>) -> shell_candy::Result<Option<()>> {
2442
if let Some(ref script) = script {

client/lib/src/device/unix_device.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::collections::HashMap;
12
use std::ops::{Deref, DerefMut};
23
use std::sync::Arc;
34
use std::time::Duration;
@@ -10,7 +11,7 @@ use tokio::task::JoinHandle;
1011
use crate::device;
1112
use crate::device::{DeviceData, Peers, HANDSHAKE_RATE_LIMIT, MAX_UDP_SIZE};
1213
use crate::device::peer::AllowedIP;
13-
use crate::device::script_run::{run_opt_script, Scripts};
14+
use crate::device::script_run::{run_opt_script, run_opt_script_with_param, Scripts};
1415
use crate::device::tun::create_async_tun;
1516
use crate::device::tunnel::{create_tcp_server, create_udp_socket};
1617
use nix::unistd::Uid;
@@ -126,9 +127,10 @@ impl Device {
126127
protocol,
127128
};
128129

129-
//run_opt_script(&Some("iptables -A FORWARD -i for0 -j ACCEPT".to_owned()))?;
130130

131-
run_opt_script(&device.scripts.post_up)?;
131+
let mut script_params:HashMap<&str, String> = HashMap::new();
132+
script_params.insert("tun", device.name.clone());
133+
run_opt_script_with_param(&device.scripts.post_up, &script_params)?;
132134
Ok(device)
133135
}
134136

@@ -157,7 +159,9 @@ impl DerefMut for Device {
157159

158160
impl Drop for Device {
159161
fn drop(&mut self) {
160-
self.task.abort();
162+
if !self.task.is_finished() {
163+
self.task.abort();
164+
}
161165
tracing::debug!("device has been dropped");
162166
}
163167
}

client/lib/src/sc_manager.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ impl <'a> AsyncEventHandler for MqttWrapper<'a> {
102102
if let Some(info) = network_message.info {
103103
match info {
104104
Peer(peer_change) => {
105-
let _ = self.sender.send(ServerMessage::SyncPeers(peer_change)).await;
105+
let _ = self.sender.send(ServerMessage::SyncPeers(network_message.network_id.clone(), peer_change)).await;
106106
}
107107
NStatus(status) => {
108108
if let Some(NetworkStatus::NetworkDelete) = NetworkStatus::from_i32(status) {

client/lib/src/server_manager.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ impl ServerManager {
8484
let _ = server_config.save_config(&config.config_path);
8585
}
8686
}
87-
server_manager.wr_manager.close().await;
87+
server_manager.wr_manager.close(&network_id).await;
8888
}
8989
ServerMessage::SyncConfig(network_token_id,wr_config) => {
9090
if let Some(config) = &server_manager.config {
@@ -94,12 +94,13 @@ impl ServerManager {
9494
.unwrap_or_else(|e| panic!("wr_manager start tun error,{:?}", e));
9595
}
9696
}
97-
ServerMessage::SyncPeers(peer_change_message) => {
97+
ServerMessage::SyncPeers(network_token_id, peer_change_message) => {
98+
9899
if let Some(public_key) = peer_change_message.remove_public_key {
99100
if server_manager.config.as_ref().map(|x|x.identity.pk_base64 != public_key).unwrap_or(true) {
100101
match Identity::get_pub_identity_from_base64(&public_key) {
101102
Ok((x_pub_key, _)) => {
102-
server_manager.wr_manager.remove_peer(&x_pub_key).await;
103+
server_manager.wr_manager.remove_peer(&network_token_id, &x_pub_key).await;
103104
}
104105
Err(_) => {
105106
tracing::warn!("peer identity parse error")
@@ -113,6 +114,7 @@ impl ServerManager {
113114
let endpoint = peer.endpoint.map(|endpoint| endpoint.parse::<SocketAddr>().unwrap());
114115
let (x_pub_key,_) = Identity::get_pub_identity_from_base64(&peer.public_key).unwrap();
115116
server_manager.wr_manager.add_peer(
117+
&network_token_id,
116118
x_pub_key,
117119
endpoint,
118120
&allowed_ip,
@@ -127,6 +129,7 @@ impl ServerManager {
127129
let endpoint = peer.endpoint.map(|endpoint| endpoint.parse::<SocketAddr>().unwrap());
128130
let (x_pub_key,_) = Identity::get_pub_identity_from_base64(&peer.public_key).unwrap();
129131
server_manager.wr_manager.add_peer(
132+
&network_token_id,
130133
x_pub_key,
131134
endpoint,
132135
&allowed_ip,
@@ -152,6 +155,6 @@ impl ServerManager {
152155
pub enum ServerMessage {
153156
// NodeStatus::Normal => start WireGuard, other => stop WireGuard
154157
StopWR{network_id:String,reason:String, delete_tun:bool},
155-
SyncPeers(crate::protobuf::config::PeerChange),
158+
SyncPeers(String, crate::protobuf::config::PeerChange),
156159
SyncConfig(String, WrConfig),
157160
}

client/lib/src/wr_manager.rs

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::collections::HashMap;
12
use std::net::{IpAddr, SocketAddr};
23
use std::str::FromStr;
34
use std::time::Duration;
@@ -12,31 +13,32 @@ use crate::device::script_run::Scripts;
1213
//WireGuard Manager
1314
// rewrite boring/Device, mainly change thread pool to tokio.
1415
pub struct WRManager {
15-
device: Option<Device>,
16+
devices: HashMap<String, Device>,
1617
}
1718

1819
impl WRManager {
1920
pub fn new() -> Self {
2021
WRManager {
21-
device: None,
22+
devices: HashMap::new(),
2223
}
2324
}
2425

25-
pub async fn remove_peer(&mut self, public_key: &x25519_dalek::PublicKey) {
26-
if let Some(device) = &mut self.device {
26+
pub async fn remove_peer(&mut self, network_token_id:&str ,public_key: &x25519_dalek::PublicKey) {
27+
if let Some(device) = self.devices.get_mut(network_token_id) {
2728
device.remove_peer(public_key).await;
2829
} else {
29-
tracing::warn!("there's no active device when remove peer")
30+
tracing::warn!("there's no active device in {network_token_id} when remove peer")
3031
}
3132
}
3233

3334
pub async fn add_peer(&mut self,
35+
network_token_id:&str,
3436
pub_key: x25519_dalek::PublicKey,
3537
endpoint: Option<SocketAddr>,
3638
allowed_ips: &[AllowedIP],
3739
ip:IpAddr,
3840
keepalive: Option<u16>) {
39-
if let Some(device) = &mut self.device {
41+
if let Some(device) = &mut self.devices.get_mut(network_token_id) {
4042
device.update_peer(
4143
pub_key,
4244
false,
@@ -64,12 +66,12 @@ impl WRManager {
6466
//TODO: check if need restart
6567
// if interface not equal, restart
6668
// check peers, remove or add new ones.
67-
let has_alive = self.is_alive();
69+
let has_alive = self.is_alive(&network_token_id);
6870
if has_alive {
69-
let node_type = self.device.as_ref().map(|x|x.node_type).unwrap_or(NodeType::NodeClient);
70-
tracing::info!("close device");
71-
self.close().await;
72-
let sleep_time = if node_type == NodeType::NodeRelay {10} else {20};
71+
let node_type = self.devices.get(&network_token_id).map(|x|x.node_type).unwrap_or(NodeType::NodeClient);
72+
tracing::info!("close {} device", network_token_id);
73+
self.close(&network_token_id).await;
74+
let sleep_time = if node_type == NodeType::NodeRelay {10} else {20};
7375
tokio::time::sleep(Duration::from_secs(sleep_time)).await;
7476
}
7577

@@ -107,7 +109,7 @@ impl WRManager {
107109
} else {
108110
server_config.info.push(NetworkInfo {
109111
tun_name: Some(wr_interface.name.clone()),
110-
network_id: network_token_id
112+
network_id: network_token_id.clone()
111113
});
112114
need_save = true;
113115
}
@@ -117,13 +119,14 @@ impl WRManager {
117119
}
118120
}
119121

120-
self.device = Some(wr_interface);
122+
self.devices.insert(network_token_id.clone(),wr_interface);
121123
for peer in wr_config.peers {
122124
let (x_pub_key,_) = Identity::get_pub_identity_from_base64(&peer.public_key)?;
123125
let endpoint = peer.endpoint.map(|v| SocketAddr::from_str(&v).unwrap());
124126
let allowed_ip:Vec<AllowedIP> = peer.allowed_ip.into_iter().map(|ip| AllowedIP::from_str(&ip).unwrap()).collect();
125127
let ip:IpAddr = peer.address.first().unwrap().parse().unwrap();
126128
self.add_peer(
129+
&network_token_id,
127130
x_pub_key,
128131
endpoint,
129132
allowed_ip.as_slice(),
@@ -135,20 +138,20 @@ impl WRManager {
135138
Ok(())
136139
}
137140

138-
pub fn is_alive(&self) -> bool { self.device.is_some() }
141+
pub fn is_alive(&self, network_token_id:&str) -> bool { self.devices.contains_key(network_token_id) }
139142

140-
pub async fn close(&mut self) {
141-
if let Some(ref mut device) = self.device.take() {
142-
device.close().await
143+
pub async fn close(&mut self, network_token_id:&str) {
144+
if let Some(device) = self.devices.get_mut(network_token_id) {
145+
device.close().await;
146+
self.devices.remove(network_token_id);
143147
}
148+
144149
}
145150

146151
pub fn device_info(&self) -> Vec<DeviceInfoResp> {
147-
self.device.as_ref().map_or(vec![], |device| {
148-
vec![DeviceInfoResp {
149-
name: device.name.clone()
150-
}]
151-
})
152+
self.devices.values().map(|device| DeviceInfoResp {
153+
name: device.name.clone()
154+
}).collect()
152155
}
153156
}
154157

0 commit comments

Comments
 (0)