Repository navigation
Expand file tree
/
Copy pathmod.rs
More file actions
131 lines (109 loc) · 3.63 KB
/
Copy pathmod.rs
File metadata and controls
131 lines (109 loc) · 3.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//! Plugin (SIP003)
//!
//! ```plain
//! +------------+ +---------------------------+
//! | SS Client +-- Local Loopback --+ Plugin Client (Tunnel) +--+
//! +------------+ +---------------------------+ |
//! |
//! Public Internet (Obfuscated/Transformed traffic) ==> |
//! |
//! +------------+ +---------------------------+ |
//! | SS Server +-- Local Loopback --+ Plugin Server (Tunnel) +--+
//! +------------+ +---------------------------+
//! ```
use std::io;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener};
use subprocess::Popen;
use subprocess::Result as PopenResult;
use config::{Config, ServerAddr};
mod ss_plugin;
mod obfs_proxy;
/// Config for plugin
#[derive(Debug, Clone)]
pub struct PluginConfig {
pub plugin: String,
pub plugin_opt: Option<String>,
}
/// Mode of Plugin
#[derive(Debug, Clone, Copy)]
pub enum PluginMode {
Server,
Client,
}
/// Plugin holder
#[derive(Debug)]
pub struct Plugin {
addr: ServerAddr,
process: Popen,
}
impl Plugin {
/// Get address of the plugin
pub fn addr(&self) -> &ServerAddr {
&self.addr
}
}
impl Drop for Plugin {
fn drop(&mut self) {
debug!("Killing Plugin {:?}", self.process);
let _ = self.process.terminate();
}
}
/// Launch plugins in config
pub fn launch_plugin(config: &mut Config, mode: PluginMode) -> io::Result<Vec<Plugin>> {
let mut plugins = Vec::new();
for svr in &mut config.server {
let mut svr_addr_opt = None;
if let Some(c) = svr.plugin() {
let loop_ip = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
let local_addr = SocketAddr::new(loop_ip, get_local_port()?);
let svr_addr = match start_plugin(c, svr.addr(), &local_addr, mode) {
Err(err) => {
panic!("Failed to start plugin \"{}\", err: {}", c.plugin, err);
}
Ok(p) => {
let svr_addr = ServerAddr::SocketAddr(local_addr);
plugins.push(Plugin {
addr: svr_addr.clone(),
process: p,
});
// Replace addr with plugin
svr_addr
}
};
match mode {
PluginMode::Client => info!("Started plugin \"{}\" on {} <-> {}", c.plugin, local_addr, svr.addr()),
PluginMode::Server => info!("Started plugin \"{}\" on {} <-> {}", c.plugin, svr.addr(), local_addr),
}
svr_addr_opt = Some(svr_addr); // Fuck borrow checker
}
if let Some(svr_addr) = svr_addr_opt {
svr.set_addr(svr_addr);
}
}
Ok(plugins)
}
fn start_plugin(plugin: &PluginConfig,
remote: &ServerAddr,
local: &SocketAddr,
mode: PluginMode)
-> PopenResult<Popen> {
if plugin.plugin == "obfsproxy" {
obfs_proxy::start_plugin(plugin, remote, local, mode)
} else {
ss_plugin::start_plugin(plugin, remote, local, mode)
}
}
fn get_local_port() -> io::Result<u16> {
let listener = TcpListener::bind(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0))?;
let addr = listener.local_addr()?;
Ok(addr.port())
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn generate_random_port() {
let port = get_local_port().unwrap();
println!("{:?}", port);
}
}