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
|
use super::mullvad_ios_runtime;
use shadowsocks_service::{
config::{
Config, ConfigType, LocalConfig, LocalInstanceConfig, ProtocolType, ServerInstanceConfig,
},
local::Server,
shadowsocks::{config::ServerConfig, crypto::CipherKind},
};
use std::{
io,
net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener},
str::FromStr,
};
use tokio::task::JoinHandle;
mod ffi;
pub fn run_forwarding_proxy(
forward_socket_addr: SocketAddr,
bridge_socket_addr: SocketAddr,
password: &str,
cipher: &str,
) -> io::Result<(u16, ShadowsocksHandle)> {
let runtime =
ShadowsocksService::new(forward_socket_addr, bridge_socket_addr, password, cipher)?;
let port = runtime.port();
let handle = runtime.run()?;
Ok((port, handle))
}
struct ShadowsocksService {
config: Config,
local_port: u16,
}
pub struct ShadowsocksHandle {
abort_handle: JoinHandle<()>,
}
impl ShadowsocksHandle {
pub fn stop(self) {
self.abort_handle.abort();
}
}
impl ShadowsocksService {
pub fn new(
forward_socket_addr: SocketAddr,
bridge_socket_addr: SocketAddr,
password: &str,
cipher: &str,
) -> io::Result<Self> {
let (config, local_port) =
Self::create_config(forward_socket_addr, bridge_socket_addr, password, cipher)?;
Ok(Self { config, local_port })
}
pub fn port(&self) -> u16 {
self.local_port
}
pub fn run(self) -> io::Result<ShadowsocksHandle> {
let runtime = mullvad_ios_runtime().map_err(io::Error::other)?;
let abort_handle = runtime.spawn(async move {
self.run_service_inner().await;
});
Ok(ShadowsocksHandle { abort_handle })
}
async fn run_service_inner(self) {
let Self { config, .. } = self;
let _ = Server::new(config)
.await
.expect("Could not create Shadowsocks server")
.run()
.await;
}
pub fn create_config(
forward_socket_addr: SocketAddr,
bridge_socket_addr: SocketAddr,
password: &str,
cipher: &str,
) -> io::Result<(Config, u16)> {
let mut cfg = Config::new(ConfigType::Local);
let free_port = get_free_port()?;
let bind_addr = SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), free_port);
let mut local_config = LocalConfig::new_with_addr(bind_addr.into(), ProtocolType::Tunnel);
local_config.forward_addr = Some(forward_socket_addr.into());
cfg.local = vec![LocalInstanceConfig::with_local_config(local_config)];
let cipher = match CipherKind::from_str(cipher) {
Ok(cipher) => cipher,
Err(err) => {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!("Invalid cipher specified: {err}"),
));
}
};
let server_config = ServerInstanceConfig::with_server_config(ServerConfig::new(
bridge_socket_addr,
password,
cipher,
));
cfg.server = vec![server_config];
Ok((cfg, free_port))
}
}
fn get_free_port() -> io::Result<u16> {
let bind_addr: SocketAddr = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0);
let port = TcpListener::bind(bind_addr)?.local_addr()?.port();
Ok(port)
}
|