Skip to content

Commit

Permalink
Remove hardcoded configuration within the SS example (#21)
Browse files Browse the repository at this point in the history
* update: remove hardcoded config parts in SS

* update: add compilation+opt script for WATM, remove clone
  • Loading branch information
erikziyunchi authored Jan 9, 2024
1 parent 931e049 commit c32920b
Show file tree
Hide file tree
Showing 13 changed files with 148 additions and 34 deletions.
19 changes: 11 additions & 8 deletions crates/wasm/src/connections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,27 +63,30 @@ impl ConnFile {
}

// A Connection normally contains both in & outbound streams + a config
pub struct Connection {
pub struct Connection<T> {
pub inbound_conn: ConnFile,
pub outbound_conn: ConnFile,

pub config: Config,
pub config: T,
}

impl Default for Connection {
impl<T: Default> Default for Connection<T> {
fn default() -> Self {
Self::new()
Self {
inbound_conn: ConnFile::new(),
outbound_conn: ConnFile::new(),
config: T::default(),
}
}
}

impl Connection {
impl<T> Connection<T> {
// 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,
}
}

Expand Down
5 changes: 2 additions & 3 deletions crates/wasm/src/dialer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use super::*;
use anyhow::{anyhow, Ok};

pub struct Dialer {
pub file_conn: Connection,
pub file_conn: Connection<Config>,
pub config: Config,
}

Expand All @@ -16,15 +16,14 @@ impl Default for Dialer {
impl Dialer {
pub fn new() -> Self {
Dialer {
file_conn: Connection::new(),
file_conn: Connection::default(),
config: Config::new(),
}
}

pub fn dial(&mut self) -> Result<i32, anyhow::Error> {
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 {
Expand Down
1 change: 0 additions & 1 deletion crates/wasm/src/v1/async_listener_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ fn _listener_creation() -> Result<i32, std::io::Error> {
}
};

// 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<u8> = bincode::serialize(&stream).expect("Failed to serialize");
Expand Down
1 change: 0 additions & 1 deletion crates/wasm/src/v1/dial_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
1 change: 0 additions & 1 deletion examples/clients/cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ fn _listener_creation() -> Result<i32, std::io::Error> {
}
};

// 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,
Expand Down
37 changes: 37 additions & 0 deletions examples/water_bins/ss_client_wasm_v1/src/config.rs
Original file line number Diff line number Diff line change
@@ -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 cipher 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,
}
}
}
7 changes: 5 additions & 2 deletions examples/water_bins/ss_client_wasm_v1/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
Expand All @@ -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::*;
Expand All @@ -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<Connection> = Mutex::new(Connection::new());
pub static ref CONN: Mutex<Connection<SSConfig>> = Mutex::new(Connection::new(SSConfig::new()));
pub static ref DIALER: Mutex<Dialer> = Mutex::new(Dialer::new());
}
81 changes: 65 additions & 16 deletions examples/water_bins/ss_client_wasm_v1/src/water.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use super::*;

use bytes::{BufMut, BytesMut};
use shadowsocks_crypto::v1::openssl_bytes_to_key;
use std::sync::Arc;

#[cfg(target_family = "wasm")]
#[export_name = "_water_init"]
Expand Down Expand Up @@ -29,7 +31,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);
Expand Down Expand Up @@ -83,6 +85,43 @@ 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);
}

// Create a Arc for the encryption key
let enc_key = Arc::new(enc_key);

info!("[WASM] Starting to listen...");

loop {
Expand All @@ -95,10 +134,18 @@ async fn _start_listen(bypass: bool) -> std::io::Result<()> {
}
};

// Clone server_addr(will be changed) for each iteration of the loop.
let server_addr_clone = server_addr.clone();

// Clone the Arc for enc_key to save resources.
let enc_key_clone = Arc::clone(&enc_key);

// 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),
}
Expand All @@ -107,7 +154,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: &[u8],
bypass: bool,
) -> std::io::Result<()> {
let mut inbound_con = Socks5Handler::new(stream);
inbound_con.socks5_greet().await.expect("Failed to greet");

Expand All @@ -120,16 +172,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: &[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
Expand All @@ -139,13 +193,8 @@ 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,
];
// 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);
let mut proxy = ProxyClientStream::from_stream(server_stream, target_addr, CIPHER_METHOD, key);

match copy_encrypted_bidirectional(CIPHER_METHOD, &mut proxy, &mut inbound_con.stream).await {
Ok((wn, rn)) => {
Expand Down Expand Up @@ -192,7 +241,7 @@ async fn _connect_bypass(
pub fn _dial_remote(target: &Address) -> Result<TcpStream, std::io::Error> {
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();
Expand Down Expand Up @@ -249,7 +298,7 @@ pub fn _listener_creation() -> Result<i32, std::io::Error> {
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,
Expand Down
Binary file modified examples/water_bins/ss_client_wasm_v1/ss_client_wasm.wasm
Binary file not shown.
24 changes: 24 additions & 0 deletions scripts/make_and_opt_wasm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/bash

# Check if the required command line arguments are provided
if [ $# -ne 2 ]; then
echo "Usage: $0 <examples/water_bins/<???>> <wasm_name>"
exit 1
fi

# Change directory to the source directory
cd "examples/water_bins/$1" || exit 1

# Build the project using cargo
cargo build --target wasm32-wasi || exit 1

# Optimize the generated wasm file
wasm-opt --strip-debug "../../../target/wasm32-wasi/debug/$2.wasm" -o "./$2.wasm" || exit 1

# Copy the optimized wasm file to the destination directory
cp "./$2.wasm" "../../../tests/test_wasm/" || exit 1

# Change directory back to the beginning directory
cd - || exit 1

echo "Wasm file $2.wasm successfully built, optimized, and copied to ./tests/test_wasm/"
Binary file modified tests/test_wasm/ss_client_wasm.wasm
100755 → 100644
Binary file not shown.
4 changes: 3 additions & 1 deletion tests/tests/ss_testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ async fn wasm_managed_shadowsocks_async() -> Result<(), Box<dyn std::error::Erro
const SERVER_ADDR: &str = "127.0.0.1:8088";
const LOCAL_ADDR: &str = "127.0.0.1:8081";

const PASSWORD: &str = "Test!23";
const PASSWORD: &str = "WATERisAwesome!23";
const METHOD: CipherKind = CipherKind::CHACHA20_POLY1305;

let cfg_str = r#"
Expand All @@ -133,6 +133,7 @@ async fn wasm_managed_shadowsocks_async() -> Result<(), Box<dyn std::error::Erro
"remote_port": 8088,
"local_address": "127.0.0.1",
"local_port": 8080,
"password": "WATERisAwesome!23",
"bypass": false
}
"#;
Expand Down Expand Up @@ -201,6 +202,7 @@ async fn wasm_managed_shadowsocks_bypass_async() -> Result<(), Box<dyn std::erro
"remote_port": 10085,
"local_address": "127.0.0.1",
"local_port": 10086,
"password": "Test!23",
"bypass": true
}
"#;
Expand Down

0 comments on commit c32920b

Please sign in to comment.