115 lines
3.5 KiB
Bash
115 lines
3.5 KiB
Bash
#!/usr/bin/env bash
|
|
set -eo pipefail
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
TACHYON_LIB="$ROOT_DIR/tachyon/files/usr/lib"
|
|
GENERATOR="$TACHYON_LIB/singbox/generator.uc"
|
|
VALIDATOR="$TACHYON_LIB/config/validator.uc"
|
|
WORK_DIR="$(mktemp -d)"
|
|
|
|
cleanup() {
|
|
rm -rf "$WORK_DIR"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
fail() {
|
|
printf 'FAIL: %s\n' "$1" >&2
|
|
exit 1
|
|
}
|
|
|
|
mkdir -p "$WORK_DIR/output.json.section-cache"
|
|
|
|
# 1. Test config generation: AWG cascading through a proxy hop, and proxy cascading through AWG
|
|
cat >"$WORK_DIR/fixture.json" <<'JSON'
|
|
{
|
|
"settings": {
|
|
".name": "settings",
|
|
".type": "settings",
|
|
"dns_server": "1.1.1.1",
|
|
"service_listen_address": "127.0.0.1"
|
|
},
|
|
"section": [
|
|
{
|
|
".name": "proxy_hop",
|
|
".type": "section",
|
|
"enabled": "1",
|
|
"action": "connection",
|
|
"selector_proxy_links": [ "socks5://127.0.0.1:1080#Hop" ]
|
|
},
|
|
{
|
|
".name": "awg_section",
|
|
".type": "section",
|
|
"enabled": "1",
|
|
"action": "awg",
|
|
"awg_version": "2.0",
|
|
"awg_private_key": "aW5ib3VuZF9wcml2YXRlX2tleQ==",
|
|
"awg_peer_public_key": "cGVlcl9wdWJsaWNfa2V5",
|
|
"awg_server_address": "192.168.1.100",
|
|
"awg_server_port": "51820",
|
|
"awg_local_address": ["10.0.0.2/24"],
|
|
"outbound_detour_enabled": "1",
|
|
"outbound_detour_section": "proxy_hop"
|
|
},
|
|
{
|
|
".name": "proxy_via_awg",
|
|
".type": "section",
|
|
"enabled": "1",
|
|
"action": "connection",
|
|
"selector_proxy_links": [ "socks5://127.0.0.1:1081#Target" ],
|
|
"outbound_detour_enabled": "1",
|
|
"outbound_detour_section": "awg_section"
|
|
}
|
|
]
|
|
}
|
|
JSON
|
|
|
|
ucode -L "$TACHYON_LIB" "$GENERATOR" generate-config-fixture \
|
|
"$WORK_DIR/fixture.json" "$WORK_DIR/output.json" "127.0.0.1"
|
|
|
|
ucode -e '
|
|
let fs = require("fs");
|
|
let config = json(fs.readfile(ARGV[0]));
|
|
|
|
function endpoint(tag) {
|
|
for (let item in config.endpoints || [])
|
|
if (item && item.tag == tag)
|
|
return item;
|
|
return null;
|
|
}
|
|
|
|
function outbound(tag) {
|
|
for (let item in config.outbounds || [])
|
|
if (item && item.tag == tag)
|
|
return item;
|
|
return null;
|
|
}
|
|
|
|
function assert(condition, message) {
|
|
if (!condition)
|
|
die(message + "\n");
|
|
}
|
|
|
|
let awg_ep = endpoint("awg_section-out");
|
|
assert(awg_ep != null, "AWG endpoint was not generated");
|
|
assert(awg_ep.detour == "proxy_hop-out", "AWG endpoint detour was not set to proxy_hop-out: " + awg_ep.detour);
|
|
|
|
let proxy_out = outbound("proxy_via_awg-1-out");
|
|
assert(proxy_out != null, "proxy_via_awg outbound was not generated");
|
|
assert(proxy_out.detour == "awg_section-out", "proxy_via_awg detour was not set to awg_section-out: " + proxy_out.detour);
|
|
' "$WORK_DIR/output.json" || fail "AWG cascade config generation"
|
|
|
|
# 2. Test validator accepts AWG detour in both directions
|
|
printf 'section1\t1\tawg\t1\tsection2\nsection2\t1\tconnection\t0\t\n' | \
|
|
ucode -L "$TACHYON_LIB" "$VALIDATOR" validate-outbound-detours || fail "validator rejected AWG -> connection cascade"
|
|
|
|
printf 'section1\t1\tconnection\t1\tsection2\nsection2\t1\tawg\t0\t\n' | \
|
|
ucode -L "$TACHYON_LIB" "$VALIDATOR" validate-outbound-detours || fail "validator rejected connection -> AWG cascade"
|
|
|
|
# 3. Test validator detects cycle involving AWG
|
|
if printf 'section1\t1\tawg\t1\tsection2\nsection2\t1\tconnection\t1\tsection1\n' | \
|
|
ucode -L "$TACHYON_LIB" "$VALIDATOR" validate-outbound-detours >/dev/null 2>&1; then
|
|
fail "validator failed to detect cycle between AWG and connection"
|
|
fi
|
|
|
|
printf 'AWG cascade checks passed\n'
|