Add all project files, configs, scripts and results
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
263
test_xray_connection.sh
Executable file
263
test_xray_connection.sh
Executable file
@@ -0,0 +1,263 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# test_xray_connection.sh — Test xray juris-xhttp outbound
|
||||
# Tests: connectivity, latency (SLA), throughput
|
||||
#
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
XRAY_BIN="/usr/local/x-ui/bin/xray-linux-amd64"
|
||||
TEST_CONFIG="/tmp/test-juris-sla.json"
|
||||
SOCKS_PORT=11080
|
||||
REMOTE_IP="83.99.190.32"
|
||||
XRAY_PID=""
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
cleanup() {
|
||||
if [[ -n "$XRAY_PID" ]] && kill -0 "$XRAY_PID" 2>/dev/null; then
|
||||
kill "$XRAY_PID" 2>/dev/null
|
||||
wait "$XRAY_PID" 2>/dev/null || true
|
||||
fi
|
||||
rm -f "$TEST_CONFIG"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
header() {
|
||||
echo ""
|
||||
echo -e "${BOLD}${CYAN}=== $1 ===${NC}"
|
||||
}
|
||||
|
||||
pass() { echo -e " ${GREEN}PASS${NC} $1"; }
|
||||
fail() { echo -e " ${RED}FAIL${NC} $1"; }
|
||||
info() { echo -e " ${YELLOW}INFO${NC} $1"; }
|
||||
|
||||
# ── Write temporary xray config ──────────────────────────────────────────────
|
||||
cat > "$TEST_CONFIG" << 'EOF'
|
||||
{
|
||||
"log": { "loglevel": "error" },
|
||||
"inbounds": [{
|
||||
"listen": "127.0.0.1",
|
||||
"port": 11080,
|
||||
"protocol": "socks",
|
||||
"settings": { "auth": "noauth", "udp": true },
|
||||
"tag": "test-socks"
|
||||
}],
|
||||
"outbounds": [{
|
||||
"tag": "juris-xhttp",
|
||||
"protocol": "vless",
|
||||
"settings": {
|
||||
"vnext": [{
|
||||
"address": "share.alogins.net",
|
||||
"port": 443,
|
||||
"users": [{
|
||||
"id": "6e422ab5-070a-43f6-8241-38cd56d23d24",
|
||||
"flow": "",
|
||||
"encryption": "none"
|
||||
}]
|
||||
}]
|
||||
},
|
||||
"streamSettings": {
|
||||
"network": "xhttp",
|
||||
"security": "reality",
|
||||
"realitySettings": {
|
||||
"fingerprint": "chrome",
|
||||
"serverName": "www.delfi.lv",
|
||||
"publicKey": "58Iqd6LuWXgvjAgo92-7KURhTp0Vj79yGF81l_iuvTw",
|
||||
"shortId": "6036d37d12c443c4",
|
||||
"spiderX": "/"
|
||||
},
|
||||
"xhttpSettings": {
|
||||
"path": "/xt-6036d37d",
|
||||
"host": "",
|
||||
"mode": "auto",
|
||||
"extra": {
|
||||
"xPaddingBytes": "100-1000",
|
||||
"xmux": {
|
||||
"maxConcurrency": "16-32",
|
||||
"maxConnections": 0,
|
||||
"cMaxReuseTimes": "64-128",
|
||||
"cMaxLifetimeMs": 0,
|
||||
"hMaxRequestTimes": "600-900",
|
||||
"hMaxReusableSecs": "1800-3000"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
EOF
|
||||
|
||||
# ── Start xray ───────────────────────────────────────────────────────────────
|
||||
header "Starting test xray instance (SOCKS on 127.0.0.1:$SOCKS_PORT)"
|
||||
|
||||
$XRAY_BIN -test -config "$TEST_CONFIG" > /dev/null 2>&1
|
||||
pass "Config validation OK"
|
||||
|
||||
$XRAY_BIN -config "$TEST_CONFIG" > /dev/null 2>&1 &
|
||||
XRAY_PID=$!
|
||||
sleep 2
|
||||
|
||||
if kill -0 "$XRAY_PID" 2>/dev/null; then
|
||||
pass "Xray started (PID $XRAY_PID)"
|
||||
else
|
||||
fail "Xray failed to start"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ── 1. Connectivity test ─────────────────────────────────────────────────────
|
||||
header "1. Connectivity"
|
||||
|
||||
PROXY="socks5h://127.0.0.1:$SOCKS_PORT"
|
||||
ERRORS=0
|
||||
|
||||
# Test: exit IP
|
||||
EXIT_IP=$(curl -s --connect-timeout 10 --max-time 15 -x "$PROXY" https://ifconfig.me 2>/dev/null || echo "FAIL")
|
||||
if [[ "$EXIT_IP" == "$REMOTE_IP" ]]; then
|
||||
pass "Exit IP: $EXIT_IP (matches remote server)"
|
||||
else
|
||||
fail "Exit IP: '$EXIT_IP' (expected $REMOTE_IP)"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
|
||||
# Test: HTTPS connectivity
|
||||
HTTP_CODE=$(curl -s -o /dev/null -w '%{http_code}' --connect-timeout 10 --max-time 15 -x "$PROXY" https://www.google.com 2>/dev/null || echo "000")
|
||||
if [[ "$HTTP_CODE" == "200" ]]; then
|
||||
pass "HTTPS to google.com: HTTP $HTTP_CODE"
|
||||
else
|
||||
fail "HTTPS to google.com: HTTP $HTTP_CODE"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
|
||||
# Test: DNS resolution through tunnel
|
||||
DNS_IP=$(curl -s --connect-timeout 10 --max-time 15 -x "$PROXY" https://dns.google/resolve?name=example.com\&type=A 2>/dev/null | python3 -c "import sys,json; print(json.load(sys.stdin)['Answer'][0]['data'])" 2>/dev/null || echo "FAIL")
|
||||
if [[ "$DNS_IP" != "FAIL" ]]; then
|
||||
pass "DNS resolution through tunnel: example.com → $DNS_IP"
|
||||
else
|
||||
fail "DNS resolution through tunnel"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
|
||||
# ── 2. Latency (SLA) ─────────────────────────────────────────────────────────
|
||||
header "2. Latency (SLA)"
|
||||
|
||||
LATENCIES=()
|
||||
LATENCY_ERRORS=0
|
||||
SAMPLES=10
|
||||
|
||||
info "Running $SAMPLES requests to measure round-trip time..."
|
||||
|
||||
for i in $(seq 1 $SAMPLES); do
|
||||
T=$(curl -s -o /dev/null -w '%{time_total}' --connect-timeout 10 --max-time 15 -x "$PROXY" https://www.gstatic.com/generate_204 2>/dev/null || echo "0")
|
||||
MS=$(echo "$T * 1000" | bc 2>/dev/null | cut -d. -f1)
|
||||
if [[ -n "$MS" && "$MS" -gt 0 ]]; then
|
||||
LATENCIES+=("$MS")
|
||||
printf " [%2d/%d] %s ms\n" "$i" "$SAMPLES" "$MS"
|
||||
else
|
||||
LATENCY_ERRORS=$((LATENCY_ERRORS + 1))
|
||||
printf " [%2d/%d] ${RED}timeout${NC}\n" "$i" "$SAMPLES"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#LATENCIES[@]} -gt 0 ]]; then
|
||||
# Calculate min/avg/max/p95
|
||||
SORTED=($(printf '%s\n' "${LATENCIES[@]}" | sort -n))
|
||||
COUNT=${#SORTED[@]}
|
||||
MIN=${SORTED[0]}
|
||||
MAX=${SORTED[$((COUNT - 1))]}
|
||||
SUM=0
|
||||
for v in "${SORTED[@]}"; do SUM=$((SUM + v)); done
|
||||
AVG=$((SUM / COUNT))
|
||||
P95_IDX=$(echo "($COUNT * 95 + 99) / 100 - 1" | bc)
|
||||
[[ $P95_IDX -ge $COUNT ]] && P95_IDX=$((COUNT - 1))
|
||||
P95=${SORTED[$P95_IDX]}
|
||||
|
||||
echo ""
|
||||
info "Latency summary ($COUNT/$SAMPLES successful):"
|
||||
echo -e " ${BOLD} Min: ${MIN} ms${NC}"
|
||||
echo -e " ${BOLD} Avg: ${AVG} ms${NC}"
|
||||
echo -e " ${BOLD} P95: ${P95} ms${NC}"
|
||||
echo -e " ${BOLD} Max: ${MAX} ms${NC}"
|
||||
|
||||
if [[ $AVG -lt 300 ]]; then
|
||||
pass "Average latency ${AVG}ms < 300ms threshold"
|
||||
elif [[ $AVG -lt 500 ]]; then
|
||||
info "Average latency ${AVG}ms — acceptable but elevated"
|
||||
else
|
||||
fail "Average latency ${AVG}ms exceeds 500ms"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
else
|
||||
fail "All latency samples failed"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
|
||||
# ── 3. Throughput ─────────────────────────────────────────────────────────────
|
||||
header "3. Throughput"
|
||||
|
||||
info "Downloading 10MB test file through tunnel..."
|
||||
|
||||
DL_RESULT=$(curl -s -o /dev/null -w '%{size_download} %{time_total} %{speed_download}' \
|
||||
--connect-timeout 15 --max-time 60 \
|
||||
-x "$PROXY" \
|
||||
"http://speedtest.tele2.net/10MB.zip" 2>/dev/null || echo "0 0 0")
|
||||
|
||||
DL_BYTES=$(echo "$DL_RESULT" | awk '{print $1}')
|
||||
DL_TIME=$(echo "$DL_RESULT" | awk '{print $2}')
|
||||
DL_SPEED=$(echo "$DL_RESULT" | awk '{print $3}')
|
||||
|
||||
if [[ "$DL_BYTES" -gt 0 ]] 2>/dev/null; then
|
||||
DL_MB=$(echo "scale=2; $DL_BYTES / 1048576" | bc)
|
||||
DL_MBPS=$(echo "scale=2; $DL_SPEED * 8 / 1048576" | bc)
|
||||
DL_TIME_S=$(echo "scale=2; $DL_TIME" | bc)
|
||||
|
||||
pass "Downloaded ${DL_MB} MB in ${DL_TIME_S}s"
|
||||
echo -e " ${BOLD} Download speed: ${DL_MBPS} Mbps${NC}"
|
||||
else
|
||||
fail "Download test failed"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
|
||||
info "Uploading 5MB test payload through tunnel..."
|
||||
|
||||
# Generate 5MB of random data and POST it
|
||||
UL_RESULT=$(dd if=/dev/urandom bs=1M count=5 2>/dev/null | \
|
||||
curl -s -o /dev/null -w '%{size_upload} %{time_total} %{speed_upload}' \
|
||||
--connect-timeout 15 --max-time 60 \
|
||||
-x "$PROXY" \
|
||||
-X POST -H "Content-Type: application/octet-stream" \
|
||||
--data-binary @- \
|
||||
"http://speedtest.tele2.net/upload.php" 2>/dev/null || echo "0 0 0")
|
||||
|
||||
UL_BYTES=$(echo "$UL_RESULT" | awk '{print $1}')
|
||||
UL_TIME=$(echo "$UL_RESULT" | awk '{print $2}')
|
||||
UL_SPEED=$(echo "$UL_RESULT" | awk '{print $3}')
|
||||
|
||||
if [[ "$UL_BYTES" -gt 0 ]] 2>/dev/null; then
|
||||
UL_MB=$(echo "scale=2; $UL_BYTES / 1048576" | bc)
|
||||
UL_MBPS=$(echo "scale=2; $UL_SPEED * 8 / 1048576" | bc)
|
||||
UL_TIME_S=$(echo "scale=2; $UL_TIME" | bc)
|
||||
|
||||
pass "Uploaded ${UL_MB} MB in ${UL_TIME_S}s"
|
||||
echo -e " ${BOLD} Upload speed: ${UL_MBPS} Mbps${NC}"
|
||||
else
|
||||
fail "Upload test failed"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
|
||||
# ── Summary ───────────────────────────────────────────────────────────────────
|
||||
header "Summary"
|
||||
|
||||
if [[ $ERRORS -eq 0 ]]; then
|
||||
echo -e " ${GREEN}${BOLD}ALL TESTS PASSED${NC}"
|
||||
else
|
||||
echo -e " ${RED}${BOLD}$ERRORS TEST(S) FAILED${NC}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
exit $ERRORS
|
||||
Reference in New Issue
Block a user