diff --git a/crates/wasm/src/connections.rs b/crates/wasm/src/connections.rs index 2ae9815..b5e45f8 100644 --- a/crates/wasm/src/connections.rs +++ b/crates/wasm/src/connections.rs @@ -63,27 +63,30 @@ impl ConnFile { } // A Connection normally contains both in & outbound streams + a config -pub struct Connection { +pub struct Connection { pub inbound_conn: ConnFile, pub outbound_conn: ConnFile, - pub config: Config, + pub config: T, } -impl Default for Connection { +impl Default for Connection { fn default() -> Self { - Self::new() + Self { + inbound_conn: ConnFile::new(), + outbound_conn: ConnFile::new(), + config: T::default(), + } } } -impl Connection { +impl Connection { // A default constructor - pub fn new() -> Self { + pub fn new(config: T) -> Self { Connection { inbound_conn: ConnFile::new(), outbound_conn: ConnFile::new(), - - config: Config::new(), + config, } } diff --git a/crates/wasm/src/dialer.rs b/crates/wasm/src/dialer.rs index 6c92b9d..4e60c89 100644 --- a/crates/wasm/src/dialer.rs +++ b/crates/wasm/src/dialer.rs @@ -3,7 +3,7 @@ use super::*; use anyhow::{anyhow, Ok}; pub struct Dialer { - pub file_conn: Connection, + pub file_conn: Connection, pub config: Config, } @@ -16,7 +16,7 @@ impl Default for Dialer { impl Dialer { pub fn new() -> Self { Dialer { - file_conn: Connection::new(), + file_conn: Connection::default(), config: Config::new(), } } @@ -24,7 +24,6 @@ impl Dialer { pub fn dial(&mut self) -> Result { info!("[WASM] running in dial func..."); - // FIXME: hardcoded the filename for now, make it a config later let fd: i32 = self.tcp_connect()?; if fd < 0 { diff --git a/crates/wasm/src/v1/async_listener_v1.rs b/crates/wasm/src/v1/async_listener_v1.rs index f4d2a23..052f58b 100644 --- a/crates/wasm/src/v1/async_listener_v1.rs +++ b/crates/wasm/src/v1/async_listener_v1.rs @@ -25,7 +25,6 @@ fn _listener_creation() -> Result { } }; - // FIXME: hardcoded the filename for now, make it a config later let stream = StreamConfigV1::init(global_conn.config.local_address.clone(), global_conn.config.local_port, "LISTEN".to_string()); let encoded: Vec = bincode::serialize(&stream).expect("Failed to serialize"); diff --git a/crates/wasm/src/v1/dial_v1.rs b/crates/wasm/src/v1/dial_v1.rs index 5c216da..07b7e32 100644 --- a/crates/wasm/src/v1/dial_v1.rs +++ b/crates/wasm/src/v1/dial_v1.rs @@ -22,7 +22,6 @@ impl Dialer { let mut fd: i32 = -1; - // FIXME: hardcoded the filename for now, make it a config later fd = self.tcp_connect()?; if fd < 0 { diff --git a/examples/clients/cli/src/cli.rs b/examples/clients/cli/src/cli.rs index 2954a06..6e3c6a2 100644 --- a/examples/clients/cli/src/cli.rs +++ b/examples/clients/cli/src/cli.rs @@ -57,7 +57,6 @@ pub fn parse_and_execute() -> Result<(), anyhow::Error> { pub fn execute(_conf: WATERConfig) -> Result<(), anyhow::Error> { // let mut water_client = runtime::WATERClient::new(conf)?; - // // FIXME: hardcoded the addr & port for now // water_client.connect("", 0)?; // loop { diff --git a/examples/water_bins/echo_client/src/async_socks5_listener.rs b/examples/water_bins/echo_client/src/async_socks5_listener.rs index 7b44a14..d09b20b 100644 --- a/examples/water_bins/echo_client/src/async_socks5_listener.rs +++ b/examples/water_bins/echo_client/src/async_socks5_listener.rs @@ -25,7 +25,7 @@ fn _listener_creation() -> Result { } }; - // FIXME: hardcoded the filename for now, make it a config later + // NOTE: hardcoded the filename for now, make it a config later let stream = StreamConfigV1::init( global_conn.config.local_address.clone(), global_conn.config.local_port, diff --git a/examples/water_bins/ss_client_wasm_v1/src/config.rs b/examples/water_bins/ss_client_wasm_v1/src/config.rs new file mode 100644 index 0000000..31651c3 --- /dev/null +++ b/examples/water_bins/ss_client_wasm_v1/src/config.rs @@ -0,0 +1,37 @@ +//! Specific config for the ss client, with more fields like password, +//! and others like cipher method(adding later) + +use serde::Deserialize; + +// A Config currently contains the local + remote ip & port +#[derive(Debug, Deserialize, Clone)] +pub struct SSConfig { + pub remote_address: String, + pub remote_port: u32, + pub local_address: String, + pub local_port: u32, + pub password: String, + pub bypass: bool, + // NOTE: will add the config for ciphter method later + // pub method: CipherKind, +} + +impl Default for SSConfig { + fn default() -> Self { + Self::new() + } +} + +// implement a constructor for the config +impl SSConfig { + pub fn new() -> Self { + SSConfig { + remote_address: String::from("example.com"), + remote_port: 8082, + local_address: String::from("127.0.0.1"), + local_port: 8080, + password: String::from("Test!23"), + bypass: false, + } + } +} diff --git a/examples/water_bins/ss_client_wasm_v1/src/lib.rs b/examples/water_bins/ss_client_wasm_v1/src/lib.rs index bf293f7..100cad4 100644 --- a/examples/water_bins/ss_client_wasm_v1/src/lib.rs +++ b/examples/water_bins/ss_client_wasm_v1/src/lib.rs @@ -7,10 +7,11 @@ use std::{ fmt::{self, Debug}, future::Future, io::{self, ErrorKind, Read}, - net::SocketAddr, + net::{IpAddr, SocketAddr}, os::fd::FromRawFd, pin::Pin, slice, + str::FromStr, sync::Mutex, task::{Context, Poll}, vec, @@ -32,6 +33,7 @@ use tracing::{debug, info, Level}; // =================== MODULES =================== pub mod aead; pub mod client; +pub mod config; pub mod crypto_io; pub mod socks5; pub mod utils; @@ -40,6 +42,7 @@ pub mod water; // =================== DEPENDENCIES FROM MODULES =================== use aead::{DecryptedReader, EncryptedWriter}; use client::*; +use config::*; use crypto_io::*; use socks5::*; use utils::*; @@ -54,6 +57,6 @@ pub static V1: i32 = 0; // create a mutable global variable stores a pointer to the config lazy_static! { - pub static ref CONN: Mutex = Mutex::new(Connection::new()); + pub static ref CONN: Mutex> = Mutex::new(Connection::new(SSConfig::new())); pub static ref DIALER: Mutex = Mutex::new(Dialer::new()); } diff --git a/examples/water_bins/ss_client_wasm_v1/src/water.rs b/examples/water_bins/ss_client_wasm_v1/src/water.rs index 6b8b5f9..25424e9 100644 --- a/examples/water_bins/ss_client_wasm_v1/src/water.rs +++ b/examples/water_bins/ss_client_wasm_v1/src/water.rs @@ -1,6 +1,7 @@ use super::*; use bytes::{BufMut, BytesMut}; +use shadowsocks_crypto::v1::openssl_bytes_to_key; #[cfg(target_family = "wasm")] #[export_name = "_water_init"] @@ -29,7 +30,7 @@ pub fn _process_config(fd: i32) { let mut config = String::new(); match config_file.read_to_string(&mut config) { Ok(_) => { - let config: Config = match serde_json::from_str(&config) { + let config: SSConfig = match serde_json::from_str(&config) { Ok(config) => config, Err(e) => { eprintln!("[WASM] > _process_config ERROR: {}", e); @@ -83,6 +84,40 @@ async fn _start_listen(bypass: bool) -> std::io::Result<()> { // Convert to tokio TcpListener. let listener = TcpListener::from_std(standard)?; + // Initialize the variables for the server address and the encryption key + let mut server_addr: Address = Address::SocketAddress(SocketAddr::from(([127, 0, 0, 1], 8088))); + let mut enc_key = vec![0u8; CIPHER_METHOD.key_len()].into_boxed_slice(); + + { + let global_conn = match CONN.lock() { + Ok(conn) => conn, + Err(e) => { + eprintln!("[WASM] > ERROR: {}", e); + return Err(std::io::Error::new( + std::io::ErrorKind::Other, + "failed to lock CONN", + )); + } + }; + + // getting the server ip address + match IpAddr::from_str(&global_conn.config.remote_address) { + Ok(ip_addr) => { + server_addr = Address::SocketAddress(SocketAddr::from(( + ip_addr, + global_conn.config.remote_port as u16, + ))); + println!("Server address: {}", server_addr); + } + Err(e) => { + eprintln!("Failed to parse IP address: {}", e); + } + } + + // getting the enc_key derived from the password + openssl_bytes_to_key(global_conn.config.password.as_bytes(), &mut enc_key); + } + info!("[WASM] Starting to listen..."); loop { @@ -95,10 +130,14 @@ async fn _start_listen(bypass: bool) -> std::io::Result<()> { } }; + // Clone server_addr + enc_key for each iteration of the loop. + let server_addr_clone = server_addr.clone(); + let enc_key_clone = enc_key.clone(); + // Spawn a background task for each new connection. tokio::spawn(async move { eprintln!("[WASM] > CONNECTED"); - match _handle_connection(socket, bypass).await { + match _handle_connection(socket, server_addr_clone, enc_key_clone, bypass).await { Ok(()) => eprintln!("[WASM] > DISCONNECTED"), Err(e) => eprintln!("[WASM] > ERROR: {}", e), } @@ -107,7 +146,12 @@ async fn _start_listen(bypass: bool) -> std::io::Result<()> { } // SS handle incoming connections -async fn _handle_connection(stream: TcpStream, bypass: bool) -> std::io::Result<()> { +async fn _handle_connection( + stream: TcpStream, + server_addr: Address, + key: Box<[u8]>, + bypass: bool, +) -> std::io::Result<()> { let mut inbound_con = Socks5Handler::new(stream); inbound_con.socks5_greet().await.expect("Failed to greet"); @@ -120,16 +164,18 @@ async fn _handle_connection(stream: TcpStream, bypass: bool) -> std::io::Result< if bypass { _connect_bypass(&target_addr, &mut inbound_con).await?; } else { - _connect(target_addr, &mut inbound_con).await?; + _connect(target_addr, server_addr, key, &mut inbound_con).await?; } Ok(()) } -async fn _connect(target_addr: Address, inbound_con: &mut Socks5Handler) -> std::io::Result<()> { - // FIXME: hardcoded server ip:address for now + only support connection with ip:port - let server_addr = Address::SocketAddress(SocketAddr::from(([127, 0, 0, 1], 8388))); - +async fn _connect( + target_addr: Address, + server_addr: Address, + key: Box<[u8]>, + inbound_con: &mut Socks5Handler, +) -> std::io::Result<()> { let server_stream = _dial_remote(&server_addr).expect("Failed to dial to SS-Server"); // Constructing the response header @@ -140,10 +186,11 @@ async fn _connect(target_addr: Address, inbound_con: &mut Socks5Handler) -> std: inbound_con.socks5_response(&mut buf).await; // FIXME: hardcoded the key which derived from the password: "Test!23" - let key = [ - 128, 218, 128, 160, 125, 72, 115, 9, 187, 165, 163, 169, 92, 177, 35, 201, 49, 245, 92, - 203, 57, 152, 63, 149, 108, 132, 60, 128, 201, 206, 82, 226, - ]; + // let key = [ + // 128, 218, 128, 160, 125, 72, 115, 9, 187, 165, 163, 169, 92, 177, 35, 201, 49, 245, 92, + // 203, 57, 152, 63, 149, 108, 132, 60, 128, 201, 206, 82, 226, + // ]; + // creating the client proxystream -- contains cryptostream with both AsyncRead and AsyncWrite implemented let mut proxy = ProxyClientStream::from_stream(server_stream, target_addr, CIPHER_METHOD, &key); @@ -192,7 +239,7 @@ async fn _connect_bypass( pub fn _dial_remote(target: &Address) -> Result { let mut tcp_dialer = Dialer::new(); - // NOTE: only support ip:port for now, add DNS resolver helper from Host later + // TODO: only support ip:port for now, add DNS resolver helper from Host later match target { Address::SocketAddress(addr) => { tcp_dialer.config.remote_address = addr.ip().to_string(); @@ -249,7 +296,7 @@ pub fn _listener_creation() -> Result { global_conn.config.local_address, global_conn.config.local_port ); - // FIXME: hardcoded the filename for now, make it a config later + // NOTE: hardcoded the filename for now, make it a config later let stream = StreamConfigV1::init( global_conn.config.local_address.clone(), global_conn.config.local_port, diff --git a/examples/water_bins/ss_client_wasm_v1/ss_client_wasm.wasm b/examples/water_bins/ss_client_wasm_v1/ss_client_wasm.wasm old mode 100644 new mode 100755 index 11e5042..13ac1cf Binary files a/examples/water_bins/ss_client_wasm_v1/ss_client_wasm.wasm and b/examples/water_bins/ss_client_wasm_v1/ss_client_wasm.wasm differ diff --git a/tests/test_wasm/ss_client_wasm.wasm b/tests/test_wasm/ss_client_wasm.wasm index 2e65958..13ac1cf 100755 Binary files a/tests/test_wasm/ss_client_wasm.wasm and b/tests/test_wasm/ss_client_wasm.wasm differ diff --git a/tests/tests/ss_testing.rs b/tests/tests/ss_testing.rs index cfb0e1b..4340b67 100644 --- a/tests/tests/ss_testing.rs +++ b/tests/tests/ss_testing.rs @@ -133,6 +133,7 @@ async fn wasm_managed_shadowsocks_async() -> Result<(), Box Result<(), Box