mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-24 17:33:46 +00:00
A cipher can round-trip perfectly against our own implementation and still be wrong: header layout, padding rules, and nonce ordering are only pinned down by talking to another implementation. This drives ss-local against rust's ssserver and rust's sslocal against ss-server, over a local origin server so it needs no network access. Covers the three SIP022 methods plus aes-256-gcm, so a regression in the legacy path shows up here too. Skips itself when shadowsocks-rust or the built binaries are absent, so it is safe to run anywhere.
122 lines
3.3 KiB
Bash
Executable File
122 lines
3.3 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Interoperability tests against shadowsocks-rust.
|
|
#
|
|
# The 2022 (SIP022) ciphers are only useful if they interoperate with other
|
|
# implementations, and a spec detail can be got wrong in a way that still
|
|
# round-trips against ourselves. This drives our binaries against
|
|
# shadowsocks-rust's in both directions.
|
|
#
|
|
# Skips (exit 0) when shadowsocks-rust is not installed, so it is safe to
|
|
# run everywhere. Install it with `brew install shadowsocks-rust` or
|
|
# `cargo install shadowsocks-rust`.
|
|
|
|
set -u
|
|
|
|
BIN_DIR="${SS_BIN_DIR:-build/shared/bin}"
|
|
ORIGIN_PORT=${ORIGIN_PORT:-18999}
|
|
SERVER_PORT=${SERVER_PORT:-18388}
|
|
LOCAL_PORT=${LOCAL_PORT:-18081}
|
|
|
|
result=0
|
|
SPID=""
|
|
LPID=""
|
|
HPID=""
|
|
|
|
cleanup() {
|
|
[ -n "$SPID" ] && kill -9 "$SPID" 2>/dev/null
|
|
[ -n "$LPID" ] && kill -9 "$LPID" 2>/dev/null
|
|
[ -n "$HPID" ] && kill -9 "$HPID" 2>/dev/null
|
|
wait 2>/dev/null
|
|
return 0
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
for tool in sslocal ssserver; do
|
|
if ! command -v "$tool" > /dev/null 2>&1; then
|
|
echo "SKIP: shadowsocks-rust ($tool) not installed"
|
|
exit 0
|
|
fi
|
|
done
|
|
|
|
for tool in curl python3 openssl; do
|
|
if ! command -v "$tool" > /dev/null 2>&1; then
|
|
echo "SKIP: $tool not available"
|
|
exit 0
|
|
fi
|
|
done
|
|
|
|
if [ ! -x "$BIN_DIR/ss-local" ] || [ ! -x "$BIN_DIR/ss-server" ]; then
|
|
echo "SKIP: shadowsocks-libev binaries not found in $BIN_DIR"
|
|
echo " (set SS_BIN_DIR to override)"
|
|
exit 0
|
|
fi
|
|
|
|
# A local origin server keeps the test off the network.
|
|
WWW_DIR="$(mktemp -d)"
|
|
echo "interop-ok" > "$WWW_DIR/index.html"
|
|
(cd "$WWW_DIR" && python3 -m http.server "$ORIGIN_PORT" --bind 127.0.0.1) \
|
|
> /dev/null 2>&1 &
|
|
HPID=$!
|
|
sleep 1
|
|
|
|
# Fetch through the SOCKS5 proxy and check we got the origin's content back.
|
|
fetch_through_proxy() {
|
|
curl -s --max-time 15 --socks5-hostname "127.0.0.1:$LOCAL_PORT" \
|
|
"http://127.0.0.1:$ORIGIN_PORT/" 2>/dev/null | grep -q "interop-ok"
|
|
}
|
|
|
|
run_case() {
|
|
local desc="$1" server_cmd="$2" client_cmd="$3"
|
|
|
|
printf '\e[0;36mrunning: %s\e[0m\n' "$desc"
|
|
|
|
$server_cmd > /dev/null 2>&1 &
|
|
SPID=$!
|
|
sleep 1
|
|
$client_cmd > /dev/null 2>&1 &
|
|
LPID=$!
|
|
sleep 2
|
|
|
|
if fetch_through_proxy; then
|
|
printf '\e[0;32mOK: %s\e[0m\n' "$desc"
|
|
else
|
|
printf '\e[0;31mFAILED: %s\e[0m\n' "$desc"
|
|
result=1
|
|
fi
|
|
|
|
kill -9 "$SPID" "$LPID" 2>/dev/null
|
|
wait "$SPID" "$LPID" 2>/dev/null
|
|
SPID=""
|
|
LPID=""
|
|
# let the listening sockets go away before the next case binds them
|
|
sleep 2
|
|
}
|
|
|
|
test_method() {
|
|
local method="$1" key_size="$2"
|
|
local psk
|
|
|
|
psk="$(openssl rand -base64 "$key_size")"
|
|
|
|
run_case "$method: libev client -> rust server" \
|
|
"ssserver -s 127.0.0.1:$SERVER_PORT -k $psk -m $method" \
|
|
"$BIN_DIR/ss-local -s 127.0.0.1 -p $SERVER_PORT -l $LOCAL_PORT -k $psk -m $method"
|
|
|
|
run_case "$method: rust client -> libev server" \
|
|
"$BIN_DIR/ss-server -s 127.0.0.1 -p $SERVER_PORT -k $psk -m $method" \
|
|
"sslocal -b 127.0.0.1:$LOCAL_PORT -s 127.0.0.1:$SERVER_PORT -k $psk -m $method"
|
|
}
|
|
|
|
# SIP022. The key sizes are fixed by the spec.
|
|
test_method 2022-blake3-aes-128-gcm 16
|
|
test_method 2022-blake3-aes-256-gcm 32
|
|
test_method 2022-blake3-chacha20-poly1305 32
|
|
|
|
# A legacy AEAD cipher, to catch a regression that only affects the old path.
|
|
test_method aes-256-gcm 32
|
|
|
|
rm -rf "$WWW_DIR"
|
|
|
|
exit $result
|