test(e2e): подключаться по ссылке из production-генератора share URI
Внутри e2e-hysteria.sh жила вторая реализация hysteria2:// URI на bash. Go-юнит-тесты проверяли production-генератор, e2e проверял свою функцию - и дрейф любой из двух реализаций оставлял обе группы тестов зелёными. Фраза "реальный клиент подключается именно по ссылке, которую выдаёт HY2XS" была неточной. Билдер ссылки вынесен в экспортируемую service.BuildHysteria2ShareURI, production-путь Hysteria2Url стал её тонкой обёрткой. Новая тестовая утилита apps/tools/share-uri печатает ссылку тем же кодом; в production-бинарь админки она не входит. Единственное расхождение с пользовательской ссылкой - insecure=1: e2e работает на самоподписанном сертификате. Расхождение ограничено с трёх сторон: - e2e отдельно печатает и проверяет production-вариант ссылки (insecure=0, корректные obfs и sni); - TestBuildHysteria2ShareURI_InsecureDiffersOnlyInThatParam доказывает, что кроме этого параметра ссылки совпадают; - TestBuildHysteria2Url_ProductionPathNeverDisablesVerification фиксирует, что production-путь никогда не передаёт insecure=1. Для запуска e2e теперь нужен Go (GO_BIN).
This commit is contained in:
+60
-14
@@ -8,15 +8,17 @@ set -euo pipefail
|
||||
# 2. TLS handshake;
|
||||
# 3. handshake с обфускацией (gecko и salamander);
|
||||
# 4. HTTP auth HY2XS: допуск разрешённого пира и отказ неразрешённому;
|
||||
# 5. клиент подключается ИМЕННО по сгенерированному hysteria2:// URI;
|
||||
# 5. клиент подключается ИМЕННО по ссылке, которую выдаёт production-код
|
||||
# генератора share URI (apps/service, через apps/tools/share-uri);
|
||||
# 6. TCP forwarding через туннель;
|
||||
# 7. UDP forwarding через туннель;
|
||||
# 8. trafficStats API: валидный и невалидный secret;
|
||||
# 9. per-peer accounting;
|
||||
# 10. перезапуск сервера и быстрое переподключение клиента.
|
||||
#
|
||||
# Скрипт самодостаточен: поднимает mock HY2XS auth endpoint, поэтому не требует
|
||||
# установленной админки и базы. Рассчитан на Debian 13 amd64.
|
||||
# Скрипт поднимает mock HY2XS auth endpoint, поэтому не требует установленной
|
||||
# админки и базы, но требует Go: ссылка берётся из production-генератора, а не
|
||||
# из второй реализации внутри теста. Рассчитан на Debian 13 amd64.
|
||||
#
|
||||
# ./tools/test/e2e-hysteria.sh
|
||||
# HYSTERIA_BIN=/tmp/hysteria ./tools/test/e2e-hysteria.sh --obfs salamander
|
||||
@@ -27,6 +29,7 @@ cd "$ROOT_DIR"
|
||||
OBFS_TYPES=()
|
||||
HYSTERIA_BIN="${HYSTERIA_BIN:-/usr/local/bin/hysteria}"
|
||||
BUN_BIN="${BUN_BIN:-bun}"
|
||||
GO_BIN="${GO_BIN:-go}"
|
||||
|
||||
SERVER_PORT="${E2E_SERVER_PORT:-34643}"
|
||||
STATS_PORT="${E2E_STATS_PORT:-34644}"
|
||||
@@ -60,6 +63,7 @@ Usage: tools/test/e2e-hysteria.sh [--obfs gecko|salamander|all]
|
||||
Environment:
|
||||
HYSTERIA_BIN path to the Hysteria binary under test (default /usr/local/bin/hysteria)
|
||||
BUN_BIN path to bun (default: bun from PATH)
|
||||
GO_BIN path to go (default: go from PATH); used to run the production share-URI generator
|
||||
EOF
|
||||
exit 2
|
||||
}
|
||||
@@ -95,6 +99,7 @@ preflight() {
|
||||
require_tool curl
|
||||
require_tool ss
|
||||
command -v "$BUN_BIN" >/dev/null 2>&1 || die "bun not found (set BUN_BIN)"
|
||||
command -v "$GO_BIN" >/dev/null 2>&1 || die "go not found (set GO_BIN)"
|
||||
|
||||
local port
|
||||
for port in "$SERVER_PORT" "$STATS_PORT" "$AUTH_PORT" \
|
||||
@@ -265,17 +270,55 @@ start_server() {
|
||||
die "server did not start listening on UDP $SERVER_PORT"
|
||||
}
|
||||
|
||||
urlencode() {
|
||||
"$BUN_BIN" -e 'process.stdout.write(encodeURIComponent(process.argv[1]))' "$1"
|
||||
}
|
||||
|
||||
# Ссылка строится ровно по официальной URI-схеме, как её генерирует админка.
|
||||
build_share_uri() {
|
||||
# Ссылка берётся из production-генератора HY2XS, а не собирается тестом.
|
||||
#
|
||||
# Раньше здесь жила вторая реализация URI на bash: расхождение между ней и
|
||||
# кодом админки оставляло зелёными обе группы тестов. Теперь реальный клиент
|
||||
# подключается ровно по той ссылке, которую выдаёт пользователю панель.
|
||||
#
|
||||
# Единственное расхождение с пользовательской ссылкой — insecure=1: e2e
|
||||
# работает на самоподписанном сертификате. Это отдельно закреплено
|
||||
# Go-тестом TestBuildHysteria2ShareURI_InsecureDiffersOnlyInThatParam.
|
||||
share_uri_from_production_code() {
|
||||
local obfs_type="$1"
|
||||
local secret="$2"
|
||||
local insecure_flag="$3"
|
||||
|
||||
printf 'hysteria2://%s@127.0.0.1:%s/?obfs=%s&obfs-password=%s&sni=%s&insecure=1' \
|
||||
"$(urlencode "$secret")" "$SERVER_PORT" "$obfs_type" "$(urlencode "$OBFS_PASSWORD")" "$SNI_NAME"
|
||||
local args=(
|
||||
--secret "$secret"
|
||||
--host 127.0.0.1
|
||||
--port "$SERVER_PORT"
|
||||
--obfs "$obfs_type"
|
||||
--obfs-password "$OBFS_PASSWORD"
|
||||
--sni "$SNI_NAME"
|
||||
)
|
||||
if [ "$insecure_flag" = "insecure" ]; then
|
||||
args+=(--insecure)
|
||||
fi
|
||||
|
||||
(cd apps && GOTOOLCHAIN=local "$GO_BIN" run ./tools/share-uri "${args[@]}") \
|
||||
|| die "production share URI generator failed"
|
||||
}
|
||||
|
||||
# Проверяем именно тот вид ссылки, который получает пользователь.
|
||||
assert_production_share_uri_shape() {
|
||||
local obfs_type="$1"
|
||||
local production_uri
|
||||
production_uri="$(share_uri_from_production_code "$obfs_type" "$VALID_SECRET" "verify")"
|
||||
|
||||
case "$production_uri" in
|
||||
hysteria2://*) ;;
|
||||
*) die "production share URI has an unexpected scheme: $production_uri" ;;
|
||||
esac
|
||||
|
||||
printf '%s' "$production_uri" | grep -q "obfs=$obfs_type" \
|
||||
|| die "production share URI does not carry obfs=$obfs_type"
|
||||
printf '%s' "$production_uri" | grep -q 'insecure=0' \
|
||||
|| die "production share URI must carry insecure=0"
|
||||
printf '%s' "$production_uri" | grep -q "sni=$SNI_NAME" \
|
||||
|| die "production share URI does not carry the SNI"
|
||||
|
||||
pass "production share URI keeps certificate verification enabled"
|
||||
}
|
||||
|
||||
# Клиент конфигурируется ИЗ share URI, а не собирается независимо: именно это
|
||||
@@ -435,7 +478,8 @@ assert_auth_rejects_unknown_peer() {
|
||||
local obfs_type="$1"
|
||||
|
||||
kill_pid CLIENT_PID
|
||||
write_client_config_from_uri "$(build_share_uri "$obfs_type" "$INVALID_SECRET")"
|
||||
write_client_config_from_uri \
|
||||
"$(share_uri_from_production_code "$obfs_type" "$INVALID_SECRET" "insecure")"
|
||||
|
||||
HYSTERIA_DISABLE_UPDATE_CHECK=1 "$HYSTERIA_BIN" client -c "$WORK_DIR/client.yaml" \
|
||||
>"$WORK_DIR/client-denied.log" 2>&1 &
|
||||
@@ -481,13 +525,15 @@ run_profile() {
|
||||
start_server
|
||||
pass "server accepted the HY2XS config and started (TLS + $obfs_type)"
|
||||
|
||||
assert_production_share_uri_shape "$obfs_type"
|
||||
|
||||
local uri
|
||||
uri="$(build_share_uri "$obfs_type" "$VALID_SECRET")"
|
||||
uri="$(share_uri_from_production_code "$obfs_type" "$VALID_SECRET" "insecure")"
|
||||
log "share URI under test: ${uri//$OBFS_PASSWORD/<obfs-password>}"
|
||||
write_client_config_from_uri "$uri"
|
||||
|
||||
start_client
|
||||
pass "client connected using the generated hysteria2:// URI (TLS + $obfs_type handshake)"
|
||||
pass "client connected using the production-generated hysteria2:// URI (TLS + $obfs_type handshake)"
|
||||
|
||||
assert_tcp_forwarding
|
||||
assert_udp_forwarding
|
||||
|
||||
Reference in New Issue
Block a user