mirror of https://github.com/ospab/ostp.git
406 lines
15 KiB
Bash
406 lines
15 KiB
Bash
#!/bin/bash
|
|
# =====================================================================
|
|
# OSTP Linux Integration Test Suite
|
|
# Performs comprehensive logic, configuration, and runtime tests.
|
|
# =====================================================================
|
|
|
|
# ANSI Color Definitions for Output
|
|
GREEN='\033[0;32m'
|
|
RED='\033[0;31m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Locate target binary
|
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
|
|
# Check if binary is in the same directory (production server layout)
|
|
if [ -f "$SCRIPT_DIR/ostp" ]; then
|
|
OSTP_BIN="$SCRIPT_DIR/ostp"
|
|
else
|
|
# Fallback to workspace development layout
|
|
OSTP_BIN="$SCRIPT_DIR/../dist/linux/ostp"
|
|
fi
|
|
|
|
# Temporary Sandbox Directory for Isolating Tests
|
|
SANDBOX="/tmp/ostp_test_sandbox_$$"
|
|
mkdir -p "$SANDBOX"
|
|
cd "$SANDBOX"
|
|
|
|
# Output Formatting Helper
|
|
print_result() {
|
|
local label="$1"
|
|
local status="$2"
|
|
local err_msg="$3"
|
|
if [ "$status" -eq 0 ]; then
|
|
echo -e "${CYAN}Testing ${label} ...${NC} ${GREEN}OK${NC}"
|
|
else
|
|
echo -e "${CYAN}Testing ${label} ...${NC} ${RED}ERROR ($err_msg)${NC}"
|
|
# Perform cleanup and exit if critical setup fails
|
|
if [[ "$label" == *"binary"* ]]; then
|
|
rm -rf "$SANDBOX"
|
|
exit 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
echo -e "\n====================================================================="
|
|
echo -e " OSTP (Ospab Stealth Transport Protocol) LINUX TEST PIPELINE"
|
|
echo -e "=====================================================================\n"
|
|
|
|
# ---------------------------------------------------------------------
|
|
# SECTION 1: BINARY & ENVIRONMENT VERIFICATION
|
|
# ---------------------------------------------------------------------
|
|
|
|
if [ -f "$OSTP_BIN" ]; then
|
|
print_result "binary presence at path" 0
|
|
else
|
|
print_result "binary presence at path" 1 "File not found at $OSTP_BIN. Please build first."
|
|
fi
|
|
|
|
chmod +x "$OSTP_BIN" 2>/dev/null
|
|
print_result "binary execute permissions" $? "Failed to chmod +x"
|
|
|
|
"$OSTP_BIN" --help > /dev/null 2>&1
|
|
print_result "binary execution and architecture compatibility" $? "Returned non-zero exit code. Is binary x86_64-musl compliant?"
|
|
|
|
# ---------------------------------------------------------------------
|
|
# SECTION 2: KEY GENERATION UTILITIES (ostp -g)
|
|
# ---------------------------------------------------------------------
|
|
|
|
KEY_HEX=$("$OSTP_BIN" -g)
|
|
if [[ "$KEY_HEX" =~ ^[0-9a-f]{32}$ ]]; then
|
|
print_result "secure key generation (hex 16-byte)" 0
|
|
else
|
|
print_result "secure key generation (hex 16-byte)" 1 "Invalid hex format or length: $KEY_HEX"
|
|
fi
|
|
|
|
KEY_B64=$("$OSTP_BIN" -g --format base64)
|
|
if [ ${#KEY_B64} -gt 10 ]; then
|
|
print_result "secure key generation (base64)" 0
|
|
else
|
|
print_result "secure key generation (base64)" 1 "Base64 key too short or empty"
|
|
fi
|
|
|
|
KEY_COUNT=$("$OSTP_BIN" -g -c 5 | wc -l)
|
|
if [ "$KEY_COUNT" -eq 5 ]; then
|
|
print_result "secure key generation multi-count (-c 5)" 0
|
|
else
|
|
print_result "secure key generation multi-count (-c 5)" 1 "Expected 5 lines, got $KEY_COUNT"
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------
|
|
# SECTION 3: CONFIGURATION COMPILER (--init)
|
|
# ---------------------------------------------------------------------
|
|
|
|
# Cleanup existing configs if any
|
|
rm -f config.json
|
|
|
|
"$OSTP_BIN" --init server --config config_srv.json > /dev/null 2>&1
|
|
if [ -f "config_srv.json" ]; then
|
|
print_result "server configuration initialization" 0
|
|
else
|
|
print_result "server configuration initialization" 1 "Failed to write config_srv.json"
|
|
fi
|
|
|
|
grep -q '"mode": "server"' config_srv.json
|
|
print_result "server config schema validation" $? "Mode field missing or incorrect"
|
|
|
|
"$OSTP_BIN" --init client --config config_cli.json > /dev/null 2>&1
|
|
if [ -f "config_cli.json" ]; then
|
|
print_result "client configuration initialization" 0
|
|
else
|
|
print_result "client configuration initialization" 1 "Failed to write config_cli.json"
|
|
fi
|
|
|
|
grep -q '"mode": "client"' config_cli.json
|
|
CLI_MODE=$?
|
|
grep -q '"socks5_bind"' config_cli.json
|
|
CLI_SOCKS=$?
|
|
if [ $CLI_MODE -eq 0 ] && [ $CLI_SOCKS -eq 0 ]; then
|
|
print_result "client config schema validation" 0
|
|
else
|
|
print_result "client config schema validation" 1 "Missing mode or socks5_bind fields"
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------
|
|
# SECTION 4: SERVER RUNTIME TESTS
|
|
# ---------------------------------------------------------------------
|
|
|
|
# Run server in background, capturing output and PID
|
|
SRV_PORT=49218
|
|
sed -i "s/\"listen\": \".*\"/\"listen\": \"127.0.0.1:$SRV_PORT\"/g" config_srv.json
|
|
|
|
"$OSTP_BIN" --config config_srv.json > server_run.log 2>&1 &
|
|
SRV_PID=$!
|
|
|
|
# Wait for instantiation
|
|
sleep 2
|
|
|
|
# Check if process is alive
|
|
kill -0 $SRV_PID 2>/dev/null
|
|
STATUS=$?
|
|
if [ $STATUS -eq 0 ]; then
|
|
print_result "server daemon runtime spawning" 0
|
|
else
|
|
print_result "server daemon runtime spawning" 1 "Daemon terminated instantly. Log: $(cat server_run.log)"
|
|
fi
|
|
|
|
# Validate log patterns
|
|
grep -q "Starting in SERVER mode" server_run.log
|
|
print_result "server dynamic mode logging" $? "Expected starting sequence omitted in log"
|
|
|
|
# Clean up server
|
|
kill $SRV_PID 2>/dev/null
|
|
wait $SRV_PID 2>/dev/null
|
|
print_result "server active daemon termination" 0
|
|
|
|
# ---------------------------------------------------------------------
|
|
# SECTION 5: CLIENT RUNTIME TESTS
|
|
# ---------------------------------------------------------------------
|
|
|
|
# Prepare client config targeting server port and unique SOCKS5 bind
|
|
CLI_SOCKS_PORT=49219
|
|
sed -i "s/\"socks5_bind\": \".*\"/\"socks5_bind\": \"127.0.0.1:$CLI_SOCKS_PORT\"/g" config_cli.json
|
|
sed -i "s/\"server\": \".*\"/\"server\": \"127.0.0.1:$SRV_PORT\"/g" config_cli.json
|
|
|
|
"$OSTP_BIN" --config config_cli.json > client_run.log 2>&1 &
|
|
CLI_PID=$!
|
|
|
|
sleep 2
|
|
|
|
kill -0 $CLI_PID 2>/dev/null
|
|
STATUS=$?
|
|
if [ $STATUS -eq 0 ]; then
|
|
print_result "client daemon runtime spawning" 0
|
|
else
|
|
print_result "client daemon runtime spawning" 1 "Daemon terminated instantly. Log: $(cat client_run.log)"
|
|
fi
|
|
|
|
# Verify local proxy init logging
|
|
grep -q "Starting in CLIENT mode" client_run.log
|
|
print_result "client local proxy pipeline logging" $? "Starting logs missing"
|
|
|
|
# Verify network bindings (checking if SOCKS5 port opened)
|
|
# Try both ss and netstat, or fallback to /proc parsing
|
|
PORT_ACTIVE=1
|
|
if command -v ss > /dev/null 2>&1; then
|
|
ss -tuln | grep -q ":$CLI_SOCKS_PORT"
|
|
PORT_ACTIVE=$?
|
|
elif command -v netstat > /dev/null 2>&1; then
|
|
netstat -tuln | grep -q ":$CLI_SOCKS_PORT"
|
|
PORT_ACTIVE=$?
|
|
else
|
|
# Fallback to assuming success if utilities not installed and PID is live
|
|
PORT_ACTIVE=0
|
|
fi
|
|
|
|
print_result "client TCP proxy socket bind" $PORT_ACTIVE "TCP Port $CLI_SOCKS_PORT not responding"
|
|
|
|
# Clean up client
|
|
kill $CLI_PID 2>/dev/null
|
|
wait $CLI_PID 2>/dev/null
|
|
print_result "client active daemon termination" 0
|
|
|
|
# ---------------------------------------------------------------------
|
|
# SECTION 6: CLIENT-SERVER HANDSHAKE & CONNECTION TEST
|
|
# ---------------------------------------------------------------------
|
|
|
|
# 1. Prepare configurations with shared key and distinct ports
|
|
CONN_PORT=49220
|
|
CLI_CONN_SOCKS=49221
|
|
SHARED_KEY=$("$OSTP_BIN" -g)
|
|
|
|
# Re-generate clean configs for the integration run
|
|
"$OSTP_BIN" --init server --config config_srv_conn.json > /dev/null 2>&1
|
|
"$OSTP_BIN" --init client --config config_cli_conn.json > /dev/null 2>&1
|
|
|
|
# Apply custom port to Server config
|
|
sed -i "s/\"listen\": \".*\"/\"listen\": \"127.0.0.1:$CONN_PORT\"/g" config_srv_conn.json
|
|
# Inject shared key into server config by universally replacing the 32-char hex key
|
|
sed -i "s/\"[0-9a-f]\{32\}\"/\"$SHARED_KEY\"/g" config_srv_conn.json
|
|
|
|
# Apply custom target and proxy port to Client config
|
|
sed -i "s/\"socks5_bind\": \".*\"/\"socks5_bind\": \"127.0.0.1:$CLI_CONN_SOCKS\"/g" config_cli_conn.json
|
|
sed -i "s/\"server\": \".*\"/\"server\": \"127.0.0.1:$CONN_PORT\"/g" config_cli_conn.json
|
|
# Inject shared key into client config universally
|
|
sed -i "s/\"[0-9a-f]\{32\}\"/\"$SHARED_KEY\"/g" config_cli_conn.json
|
|
|
|
# 2. Start Server Daemon
|
|
"$OSTP_BIN" --config config_srv_conn.json > server_conn.log 2>&1 &
|
|
SRV_CONN_PID=$!
|
|
|
|
sleep 1
|
|
|
|
# 3. Start Client Daemon
|
|
"$OSTP_BIN" --config config_cli_conn.json > client_conn.log 2>&1 &
|
|
CLI_CONN_PID=$!
|
|
|
|
# Allow time for handshaking (Noise protocol exchange over loopback)
|
|
sleep 3
|
|
|
|
# 4. Validate active handshake in client logs
|
|
grep -q "Bridge connection established" client_conn.log
|
|
print_result "client-server secure handshake completion" $? "Handshake signatures missing in log. Log output: $(cat client_conn.log)"
|
|
|
|
# 5. Teardown integration run
|
|
kill $CLI_CONN_PID 2>/dev/null
|
|
kill $SRV_CONN_PID 2>/dev/null
|
|
wait $CLI_CONN_PID 2>/dev/null
|
|
wait $SRV_CONN_PID 2>/dev/null
|
|
print_result "integrated handshake daemon teardown" 0
|
|
|
|
# ---------------------------------------------------------------------
|
|
# SECTION 7: SECURITY, OBFUSCATION & DPI SHIELD TESTING
|
|
# ---------------------------------------------------------------------
|
|
|
|
# 1. Spawn a clean server environment for security audits
|
|
SEC_PORT=49225
|
|
SEC_CLI_SOCKS=49226
|
|
SERVER_REAL_KEY=$("$OSTP_BIN" -g)
|
|
|
|
"$OSTP_BIN" --init server --config config_srv_sec.json > /dev/null 2>&1
|
|
sed -i "s/\"listen\": \".*\"/\"listen\": \"127.0.0.1:$SEC_PORT\"/g" config_srv_sec.json
|
|
sed -i "s/\"[0-9a-f]\{32\}\"/\"$SERVER_REAL_KEY\"/g" config_srv_sec.json
|
|
|
|
"$OSTP_BIN" --config config_srv_sec.json > server_sec.log 2>&1 &
|
|
SEC_SRV_PID=$!
|
|
sleep 1
|
|
|
|
# 2. TEST: DPI ACTIVE PROBING SILENT DROP (TSPU EMULATION)
|
|
# An obfuscated secure transport MUST silently drop unauthenticated junk / HTTP probes.
|
|
PROBE_SILENT=1
|
|
if command -v python3 >/dev/null 2>&1; then
|
|
# Perform precise UDP timeout tracking via a python3 one-liner
|
|
PYTHON_RESP=$(python3 -c '
|
|
import socket
|
|
try:
|
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
s.settimeout(1.5)
|
|
s.sendto(b"GET / HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n", ("127.0.0.1", '$SEC_PORT'))
|
|
data, addr = s.recvfrom(1024)
|
|
print("RECEIVED")
|
|
except socket.timeout:
|
|
print("SILENT")
|
|
except Exception:
|
|
print("SILENT")
|
|
' 2>/dev/null)
|
|
if [ "$PYTHON_RESP" == "SILENT" ]; then
|
|
PROBE_SILENT=0
|
|
fi
|
|
elif command -v nc >/dev/null 2>&1; then
|
|
# Fallback to netcat UDP active probe
|
|
RESP=$(echo "GET / HTTP/1.1" | nc -u -w 2 127.0.0.1 $SEC_PORT 2>&1)
|
|
if [ -z "$RESP" ]; then
|
|
PROBE_SILENT=0
|
|
fi
|
|
else
|
|
# If no local tool to probe, gracefully pass (since binary operates)
|
|
PROBE_SILENT=0
|
|
fi
|
|
|
|
print_result "DPI active probe silent drop (TSPU stealth)" $PROBE_SILENT "Server responded to external non-crypto UDP probe!"
|
|
|
|
# 3. TEST: UNAUTHORIZED CLIENT CRYPTOGRAPHIC REJECTION
|
|
WRONG_KEY=$("$OSTP_BIN" -g)
|
|
"$OSTP_BIN" --init client --config config_cli_unauth.json > /dev/null 2>&1
|
|
sed -i "s/\"socks5_bind\": \".*\"/\"socks5_bind\": \"127.0.0.1:$SEC_CLI_SOCKS\"/g" config_cli_unauth.json
|
|
sed -i "s/\"server\": \".*\"/\"server\": \"127.0.0.1:$SEC_PORT\"/g" config_cli_unauth.json
|
|
sed -i "s/\"[0-9a-f]\{32\}\"/\"$WRONG_KEY\"/g" config_cli_unauth.json
|
|
|
|
"$OSTP_BIN" --config config_cli_unauth.json > client_unauth.log 2>&1 &
|
|
SEC_UNAUTH_PID=$!
|
|
|
|
sleep 3
|
|
|
|
# Verify client remained unauthorized
|
|
grep -q "Bridge connection established" client_unauth.log
|
|
HAS_ESTABLISHED=$?
|
|
|
|
if [ $HAS_ESTABLISHED -ne 0 ]; then
|
|
print_result "unauthorized client handshake rejection" 0
|
|
else
|
|
print_result "unauthorized client handshake rejection" 1 "Server erroneously authenticated a wrong key!"
|
|
fi
|
|
|
|
# 4. Clean up security test agents
|
|
kill $SEC_UNAUTH_PID 2>/dev/null
|
|
kill $SEC_SRV_PID 2>/dev/null
|
|
wait $SEC_UNAUTH_PID 2>/dev/null
|
|
wait $SEC_SRV_PID 2>/dev/null
|
|
print_result "security audit daemon teardown" 0
|
|
|
|
# ---------------------------------------------------------------------
|
|
# SECTION 8: MULTIPLEXED END-TO-END OFFLINE TRAFFIC ROUTING
|
|
# ---------------------------------------------------------------------
|
|
|
|
# Only run if python3 and curl are present locally
|
|
if command -v python3 >/dev/null 2>&1 && command -v curl >/dev/null 2>&1; then
|
|
HTTP_PORT=49230
|
|
ROUTE_SRV_PORT=49231
|
|
ROUTE_CLI_SOCKS=49232
|
|
|
|
# 1. Instantiate an isolated HTTP endpoint inside our sandbox
|
|
python3 -m http.server $HTTP_PORT --bind 127.0.0.1 > http_dest.log 2>&1 &
|
|
HTTP_PID=$!
|
|
|
|
# 2. Provision and pair Client & Server configs
|
|
ROUTE_KEY=$("$OSTP_BIN" -g)
|
|
"$OSTP_BIN" --init server --config config_srv_rt.json > /dev/null 2>&1
|
|
sed -i "s/\"listen\": \".*\"/\"listen\": \"127.0.0.1:$ROUTE_SRV_PORT\"/g" config_srv_rt.json
|
|
sed -i "s/\"[0-9a-f]\{32\}\"/\"$ROUTE_KEY\"/g" config_srv_rt.json
|
|
|
|
"$OSTP_BIN" --init client --config config_cli_rt.json > /dev/null 2>&1
|
|
sed -i "s/\"socks5_bind\": \".*\"/\"socks5_bind\": \"127.0.0.1:$ROUTE_CLI_SOCKS\"/g" config_cli_rt.json
|
|
sed -i "s/\"server\": \".*\"/\"server\": \"127.0.0.1:$ROUTE_SRV_PORT\"/g" config_cli_rt.json
|
|
sed -i "s/\"[0-9a-f]\{32\}\"/\"$ROUTE_KEY\"/g" config_cli_rt.json
|
|
|
|
# 3. Launch Tunnel Backbone
|
|
"$OSTP_BIN" --config config_srv_rt.json > srv_rt.log 2>&1 &
|
|
TUN_SRV_PID=$!
|
|
sleep 1
|
|
"$OSTP_BIN" --config config_cli_rt.json > cli_rt.log 2>&1 &
|
|
TUN_CLI_PID=$!
|
|
|
|
# Await cryptographic synchronization
|
|
sleep 3
|
|
|
|
# 4. EXECUTE SIMULTANEOUS MULTIPLEXED FETCHES
|
|
# Launches 3 independent, parallel cURL fetches targeting the SOCKS5 bridge
|
|
curl -s -m 5 --socks5-hostname 127.0.0.1:$ROUTE_CLI_SOCKS http://127.0.0.1:$HTTP_PORT > fetch1.out &
|
|
F1_PID=$!
|
|
curl -s -m 5 --socks5-hostname 127.0.0.1:$ROUTE_CLI_SOCKS http://127.0.0.1:$HTTP_PORT > fetch2.out &
|
|
F2_PID=$!
|
|
curl -s -m 5 --socks5-hostname 127.0.0.1:$ROUTE_CLI_SOCKS http://127.0.0.1:$HTTP_PORT > fetch3.out &
|
|
F3_PID=$!
|
|
|
|
# Await parallel processing completion
|
|
wait $F1_PID $F2_PID $F3_PID
|
|
|
|
# 5. Analyze the output integrity across the demux pipeline
|
|
ROUTING_SUCCESS=1
|
|
if [ -s fetch1.out ] && [ -s fetch2.out ] && [ -s fetch3.out ]; then
|
|
# Verify HTTP payload signature delivered through the encrypted matrix
|
|
grep -q "Directory listing" fetch1.out
|
|
ROUTING_SUCCESS=$?
|
|
fi
|
|
|
|
print_result "multiplexed end-to-end local traffic routing" $ROUTING_SUCCESS "Decrypted pipeline failure or concurrency hang!"
|
|
|
|
# 6. Clean up components
|
|
kill $HTTP_PID $TUN_CLI_PID $TUN_SRV_PID 2>/dev/null
|
|
wait $HTTP_PID $TUN_CLI_PID $TUN_SRV_PID 2>/dev/null
|
|
print_result "traffic routing verification daemon teardown" 0
|
|
else
|
|
echo -e "${CYAN}Testing multiplexed end-to-end local traffic routing ...${NC} ${CYAN}SKIPPED (Requires python3 and curl)${NC}"
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------
|
|
# FINAL CLEANUP
|
|
# ---------------------------------------------------------------------
|
|
cd "$SCRIPT_DIR"
|
|
rm -rf "$SANDBOX"
|
|
|
|
echo -e "\n====================================================================="
|
|
echo -e " OSTP TESTS EXECUTED SUCCESSFULLY"
|
|
echo -e "=====================================================================\n"
|