Skip to content

Commit

Permalink
fix: fix state machine logic error in obfs's tls impl; add docker tes…
Browse files Browse the repository at this point in the history
…ts for obfs (#437)

* fix: fix state machine logic error in obfs's tls impl; add docker tests for obfs

* add target_arch cfg for obfs's docker test
  • Loading branch information
VendettaReborn authored May 30, 2024
1 parent 6ff0a72 commit e62ed81
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 39 deletions.
68 changes: 68 additions & 0 deletions clash_lib/src/proxy/shadowsocks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use super::{
AnyOutboundHandler, AnyStream, ConnectorType, OutboundType,
};

#[derive(Clone, Copy)]
pub enum SimpleOBFSMode {
Http,
Tls,
Expand Down Expand Up @@ -451,4 +452,71 @@ mod tests {
// see: https://github.com/ihciah/shadow-tls/issues/54
run_test_suites_and_cleanup(handler, chained, Suite::tcp_tests()).await
}

async fn get_obfs_runner(

Check warning on line 456 in clash_lib/src/proxy/shadowsocks/mod.rs

View workflow job for this annotation

GitHub Actions / i686-unknown-linux-gnu

function `get_obfs_runner` is never used

Check warning on line 456 in clash_lib/src/proxy/shadowsocks/mod.rs

View workflow job for this annotation

GitHub Actions / i686-unknown-linux-gnu-static-crt

function `get_obfs_runner` is never used

Check warning on line 456 in clash_lib/src/proxy/shadowsocks/mod.rs

View workflow job for this annotation

GitHub Actions / aarch64-unknown-linux-gnu

function `get_obfs_runner` is never used

Check warning on line 456 in clash_lib/src/proxy/shadowsocks/mod.rs

View workflow job for this annotation

GitHub Actions / armv7-unknown-linux-gnueabi

function `get_obfs_runner` is never used

Check warning on line 456 in clash_lib/src/proxy/shadowsocks/mod.rs

View workflow job for this annotation

GitHub Actions / aarch64-unknown-linux-gnu-static-crt

function `get_obfs_runner` is never used

Check warning on line 456 in clash_lib/src/proxy/shadowsocks/mod.rs

View workflow job for this annotation

GitHub Actions / armv7-unknown-linux-gnueabi-static-crt

function `get_obfs_runner` is never used

Check warning on line 456 in clash_lib/src/proxy/shadowsocks/mod.rs

View workflow job for this annotation

GitHub Actions / armv7-unknown-linux-musleabihf

function `get_obfs_runner` is never used
ss_port: u16,
obfs_port: u16,
mode: SimpleOBFSMode,
) -> anyhow::Result<DockerTestRunner> {
let ss_server_env = format!("127.0.0.1:{}", ss_port);
let port = format!("{}", obfs_port);
let mode = match mode {
SimpleOBFSMode::Http => "http",
SimpleOBFSMode::Tls => "tls",
};
DockerTestRunnerBuilder::new()
.image(IMAGE_OBFS)
.cmd(&[
"obfs-server",
"-p",
&port,
"--obfs",
&mode,
"-r",
&ss_server_env,
])
.build()
.await
}

async fn test_ss_obfs_inner(mode: SimpleOBFSMode) -> anyhow::Result<()> {

Check warning on line 482 in clash_lib/src/proxy/shadowsocks/mod.rs

View workflow job for this annotation

GitHub Actions / i686-unknown-linux-gnu

function `test_ss_obfs_inner` is never used

Check warning on line 482 in clash_lib/src/proxy/shadowsocks/mod.rs

View workflow job for this annotation

GitHub Actions / i686-unknown-linux-gnu-static-crt

function `test_ss_obfs_inner` is never used

Check warning on line 482 in clash_lib/src/proxy/shadowsocks/mod.rs

View workflow job for this annotation

GitHub Actions / aarch64-unknown-linux-gnu

function `test_ss_obfs_inner` is never used

Check warning on line 482 in clash_lib/src/proxy/shadowsocks/mod.rs

View workflow job for this annotation

GitHub Actions / armv7-unknown-linux-gnueabi

function `test_ss_obfs_inner` is never used

Check warning on line 482 in clash_lib/src/proxy/shadowsocks/mod.rs

View workflow job for this annotation

GitHub Actions / aarch64-unknown-linux-gnu-static-crt

function `test_ss_obfs_inner` is never used

Check warning on line 482 in clash_lib/src/proxy/shadowsocks/mod.rs

View workflow job for this annotation

GitHub Actions / armv7-unknown-linux-gnueabi-static-crt

function `test_ss_obfs_inner` is never used

Check warning on line 482 in clash_lib/src/proxy/shadowsocks/mod.rs

View workflow job for this annotation

GitHub Actions / armv7-unknown-linux-musleabihf

function `test_ss_obfs_inner` is never used
let obfs_port = 10002;
let ss_port = 10004;
let opts = HandlerOptions {
name: "test-ss".to_owned(),
common_opts: Default::default(),
server: LOCAL_ADDR.to_owned(),
port: obfs_port,
password: PASSWORD.to_owned(),
cipher: CIPHER.to_owned(),
plugin_opts: Some(OBFSOption::Simple(SimpleOBFSOption {
host: "www.bing.com".to_owned(),
mode,
})),
udp: false,
};

let handler: Arc<dyn OutboundHandler> = Handler::new(opts);
let mut chained = MultiDockerTestRunner::default();
chained.add(get_ss_runner(ss_port)).await;
chained.add(get_obfs_runner(ss_port, obfs_port, mode)).await;
run_test_suites_and_cleanup(handler, chained, &Suite::tcp_tests()).await
}

#[cfg(target_arch = "x86_64")]
#[tokio::test]
#[serial_test::serial]
async fn test_ss_obfs_http() -> anyhow::Result<()> {
test_ss_obfs_inner(SimpleOBFSMode::Http).await
}

#[cfg(target_arch = "x86_64")]
#[tokio::test]
#[serial_test::serial]
async fn test_ss_obfs_tls() -> anyhow::Result<()> {
let _ = tracing_subscriber::fmt()
.with_max_level(tracing::Level::DEBUG)
.try_init();
test_ss_obfs_inner(SimpleOBFSMode::Tls).await
}
}
80 changes: 41 additions & 39 deletions clash_lib/src/proxy/shadowsocks/simple_obfs/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,51 +144,53 @@ fn reading(
let this = this.get_mut();
let mut inner = Pin::new(&mut this.inner);

match this.read_state {
ReadState::Idle => {
// 1. discard n bytes
let mut buffer = vec![0; discard_n];
let fut = inner.read_exact(&mut buffer);
pin_mut!(fut);
match ready!(fut.poll(cx)) {
Ok(_) => {
this.read_state = ReadState::Parsing;
Poll::Pending // do next step
loop {
match this.read_state {
ReadState::Idle => {
// 1. discard n bytes
let mut buffer = vec![0; discard_n];
let fut = inner.read_exact(&mut buffer);
pin_mut!(fut);
match ready!(fut.poll(cx)) {
Ok(_) => {
this.read_state = ReadState::Parsing;
continue;
}
Err(e) => return Poll::Ready(Err(e)),
}
Err(e) => Poll::Ready(Err(e)),
}
}
ReadState::Parsing => {
// 2. read 2 bytes as length
let mut buffer = vec![0; 2];
let fut = inner.read_exact(&mut buffer);
pin_mut!(fut);
match ready!(fut.poll(cx)) {
Ok(_) => {
let length = BigEndian::read_u16(&buffer[..2]) as usize;
this.read_state = ReadState::Reading(length);
Poll::Pending // do next step
ReadState::Parsing => {
// 2. read 2 bytes as length
let mut buffer = vec![0; 2];
let fut = inner.read_exact(&mut buffer);
pin_mut!(fut);
match ready!(fut.poll(cx)) {
Ok(_) => {
let length = BigEndian::read_u16(&buffer[..2]) as usize;
this.read_state = ReadState::Reading(length);
continue;
}
Err(e) => return Poll::Ready(Err(e)),
}
Err(e) => Poll::Ready(Err(e)),
}
}
ReadState::Reading(length) => {
// 3. read length bytes
let remaining = buf.remaining();
let len = length.min(remaining);
let mut buffer = vec![0; len];
let fut = inner.read_exact(&mut buffer);
pin_mut!(fut);
match ready!(fut.poll(cx)) {
Ok(_) => {
buf.put_slice(&buffer);
if length > remaining {
this.remain = length - remaining;
ReadState::Reading(length) => {
// 3. read length bytes
let remaining = buf.remaining();
let len = length.min(remaining);
let mut buffer = vec![0; len];
let fut = inner.read_exact(&mut buffer);
pin_mut!(fut);
match ready!(fut.poll(cx)) {
Ok(_) => {
buf.put_slice(&buffer);
if length > remaining {
this.remain = length - remaining;
}
this.read_state = ReadState::Idle;
return Poll::Ready(Ok(()));
}
this.read_state = ReadState::Idle;
Poll::Ready(Ok(()))
Err(e) => return Poll::Ready(Err(e)),
}
Err(e) => Poll::Ready(Err(e)),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions clash_lib/src/proxy/utils/test_utils/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub const LOCAL_ADDR: &str = "127.0.0.1";
pub const IMAGE_WG: &str = "lscr.io/linuxserver/wireguard:1.0.20210914-legacy";
pub const IMAGE_SS_RUST: &str = "ghcr.io/shadowsocks/ssserver-rust:latest";
pub const IMAGE_SHADOW_TLS: &str = "ghcr.io/ihciah/shadow-tls:latest";
pub const IMAGE_OBFS: &str = "liaohuqiu/simple-obfs:latest";

Check warning on line 6 in clash_lib/src/proxy/utils/test_utils/consts.rs

View workflow job for this annotation

GitHub Actions / i686-unknown-linux-gnu

constant `IMAGE_OBFS` is never used

Check warning on line 6 in clash_lib/src/proxy/utils/test_utils/consts.rs

View workflow job for this annotation

GitHub Actions / i686-unknown-linux-gnu-static-crt

constant `IMAGE_OBFS` is never used

Check warning on line 6 in clash_lib/src/proxy/utils/test_utils/consts.rs

View workflow job for this annotation

GitHub Actions / aarch64-unknown-linux-gnu

constant `IMAGE_OBFS` is never used

Check warning on line 6 in clash_lib/src/proxy/utils/test_utils/consts.rs

View workflow job for this annotation

GitHub Actions / armv7-unknown-linux-gnueabi

constant `IMAGE_OBFS` is never used

Check warning on line 6 in clash_lib/src/proxy/utils/test_utils/consts.rs

View workflow job for this annotation

GitHub Actions / aarch64-unknown-linux-gnu-static-crt

constant `IMAGE_OBFS` is never used

Check warning on line 6 in clash_lib/src/proxy/utils/test_utils/consts.rs

View workflow job for this annotation

GitHub Actions / armv7-unknown-linux-gnueabi-static-crt

constant `IMAGE_OBFS` is never used

Check warning on line 6 in clash_lib/src/proxy/utils/test_utils/consts.rs

View workflow job for this annotation

GitHub Actions / armv7-unknown-linux-musleabihf

constant `IMAGE_OBFS` is never used
pub const IMAGE_TROJAN_GO: &str = "p4gefau1t/trojan-go:latest";
pub const IMAGE_VMESS: &str = "v2fly/v2fly-core:v4.45.2";
pub const IMAGE_XRAY: &str = "teddysun/xray:latest";

0 comments on commit e62ed81

Please sign in to comment.