fix(singbox): cascade section-level server exclusions to URLTest and Priority groups (#89)
This commit is contained in:
@@ -652,6 +652,48 @@ function is_valid_detour(config, tag) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function section_excluded_candidate_tags(section, candidate_tags, state) {
|
||||||
|
let mode = connections.dashboard_filter_mode(section);
|
||||||
|
if (mode != "exclude" && mode != "mixed")
|
||||||
|
return [];
|
||||||
|
|
||||||
|
let exclude_names = connections.dashboard_exclude_outbounds(section);
|
||||||
|
let exclude_regex = connections.dashboard_exclude_regex(section);
|
||||||
|
let exclude_countries = connections.dashboard_exclude_countries(section);
|
||||||
|
let exclude_proxy_parameters = connections.dashboard_exclude_proxy_parameters(section);
|
||||||
|
let exclude_protocols = connections.dashboard_exclude_protocols(section);
|
||||||
|
let exclude_transports = connections.dashboard_exclude_transports(section);
|
||||||
|
let exclude_securities = connections.dashboard_exclude_securities(section);
|
||||||
|
|
||||||
|
let has_exclude_criteria = length(exclude_names) > 0 ||
|
||||||
|
length(exclude_regex) > 0 ||
|
||||||
|
length(exclude_countries) > 0 ||
|
||||||
|
(exclude_proxy_parameters && (
|
||||||
|
length(exclude_protocols) > 0 ||
|
||||||
|
length(exclude_transports) > 0 ||
|
||||||
|
length(exclude_securities) > 0
|
||||||
|
));
|
||||||
|
|
||||||
|
if (!has_exclude_criteria)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
return urltest_matching_candidate_outbounds(
|
||||||
|
candidate_tags,
|
||||||
|
object_or_empty(object_or_empty(state.outboundMetadata).names),
|
||||||
|
dashboard_country_metadata(section, state),
|
||||||
|
exclude_names,
|
||||||
|
exclude_regex,
|
||||||
|
exclude_countries,
|
||||||
|
object_or_empty(state.outboundMetadata),
|
||||||
|
exclude_proxy_parameters,
|
||||||
|
"or",
|
||||||
|
exclude_protocols,
|
||||||
|
exclude_transports,
|
||||||
|
exclude_securities,
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function add_proxy_selector(config, section, selector_tags, urltest_candidate_tags, state) {
|
function add_proxy_selector(config, section, selector_tags, urltest_candidate_tags, state) {
|
||||||
let section_name = section[".name"];
|
let section_name = section[".name"];
|
||||||
let selector_tag = outbound_tag(section_name);
|
let selector_tag = outbound_tag(section_name);
|
||||||
@@ -661,8 +703,13 @@ function add_proxy_selector(config, section, selector_tags, urltest_candidate_ta
|
|||||||
let priority_tags = [];
|
let priority_tags = [];
|
||||||
let group_outbounds = {};
|
let group_outbounds = {};
|
||||||
|
|
||||||
|
let section_excluded = section_excluded_candidate_tags(section, urltest_candidate_tags, state);
|
||||||
|
let group_candidate_tags = length(section_excluded) > 0
|
||||||
|
? urltest_exclude_outbounds(urltest_candidate_tags, section_excluded)
|
||||||
|
: urltest_candidate_tags;
|
||||||
|
|
||||||
for (let urltest_id in connections.urltests(section)) {
|
for (let urltest_id in connections.urltests(section)) {
|
||||||
let urltest = add_urltest_outbound(config, section, urltest_id, urltest_candidate_tags, state);
|
let urltest = add_urltest_outbound(config, section, urltest_id, group_candidate_tags, state);
|
||||||
remember_dashboard_group_outbounds(
|
remember_dashboard_group_outbounds(
|
||||||
group_outbounds,
|
group_outbounds,
|
||||||
connections.urltest_display_name(section, urltest_id),
|
connections.urltest_display_name(section, urltest_id),
|
||||||
@@ -675,7 +722,7 @@ function add_proxy_selector(config, section, selector_tags, urltest_candidate_ta
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (let group_id in connections.priority_groups(section)) {
|
for (let group_id in connections.priority_groups(section)) {
|
||||||
let priority = add_priority_group_outbound(config, section, group_id, urltest_candidate_tags, state);
|
let priority = add_priority_group_outbound(config, section, group_id, group_candidate_tags, state);
|
||||||
remember_dashboard_group_outbounds(
|
remember_dashboard_group_outbounds(
|
||||||
group_outbounds,
|
group_outbounds,
|
||||||
connections.priority_group_display_name(section, group_id),
|
connections.priority_group_display_name(section, group_id),
|
||||||
|
|||||||
@@ -186,4 +186,96 @@ if (mixed.default != "proxy-urltest-ut_main-out")
|
|||||||
"$WORK_DIR/exclude-config.json" "$WORK_DIR/mixed-config.json" ||
|
"$WORK_DIR/exclude-config.json" "$WORK_DIR/mixed-config.json" ||
|
||||||
fail "dashboard server filter regression"
|
fail "dashboard server filter regression"
|
||||||
|
|
||||||
|
# ─── Issue #89: Section server exclusion cascades to URLTest & Priority groups ─
|
||||||
|
cat >"$WORK_DIR/issue89.json" <<'JSON'
|
||||||
|
{
|
||||||
|
"settings": {
|
||||||
|
".name": "settings",
|
||||||
|
".type": "settings",
|
||||||
|
"dns_server": [ "77.88.8.8" ],
|
||||||
|
"bootstrap_dns_server": [ "77.88.8.8" ]
|
||||||
|
},
|
||||||
|
"section": [
|
||||||
|
{
|
||||||
|
".name": "proxy",
|
||||||
|
".type": "section",
|
||||||
|
"enabled": "1",
|
||||||
|
"action": "connection",
|
||||||
|
"outbound_jsons": [
|
||||||
|
"{\"type\":\"vless\",\"tag\":\"🇳🇱 Amsterdam\",\"server\":\"nl.example\",\"server_port\":443,\"uuid\":\"00000000-0000-4000-8000-000000000001\"}",
|
||||||
|
"{\"type\":\"vless\",\"tag\":\"🇷🇺 Moscow\",\"server\":\"ru.example\",\"server_port\":443,\"uuid\":\"00000000-0000-4000-8000-000000000002\"}",
|
||||||
|
"{\"type\":\"vless\",\"tag\":\"🇩🇪 Berlin\",\"server\":\"de.example\",\"server_port\":443,\"uuid\":\"00000000-0000-4000-8000-000000000003\"}"
|
||||||
|
],
|
||||||
|
"dashboard_filter_mode": "exclude",
|
||||||
|
"dashboard_detect_server_country": "flag_emoji",
|
||||||
|
"dashboard_exclude_countries": [ "RU" ]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"urltest": [
|
||||||
|
{
|
||||||
|
".name": "ut_auto",
|
||||||
|
".type": "urltest",
|
||||||
|
"section": "proxy",
|
||||||
|
"name": "Auto Main",
|
||||||
|
"filter_mode": "disabled"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"priority_group": [
|
||||||
|
{
|
||||||
|
".name": "pg_auto",
|
||||||
|
".type": "priority_group",
|
||||||
|
"section": "proxy",
|
||||||
|
"name": "Priority Main"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"priority_level": [
|
||||||
|
{
|
||||||
|
".name": "pl_auto",
|
||||||
|
".type": "priority_level",
|
||||||
|
"group": "pg_auto",
|
||||||
|
"name": "Level 1",
|
||||||
|
"order": "0",
|
||||||
|
"filter_mode": "disabled"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
JSON
|
||||||
|
|
||||||
|
validate_fixture "$WORK_DIR/issue89.json" >/dev/null || fail "issue89 fixture validation"
|
||||||
|
generate_config "$WORK_DIR/issue89.json" "$WORK_DIR/issue89-config.json"
|
||||||
|
|
||||||
|
ucode -e '
|
||||||
|
let fs = require("fs");
|
||||||
|
function fail(message) { die(message + "\n"); }
|
||||||
|
function outbound_by_tag(config, tag) {
|
||||||
|
for (let outbound in config.outbounds || [])
|
||||||
|
if (outbound && outbound.tag == tag)
|
||||||
|
return outbound;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
function assert_array(value, expected, label) {
|
||||||
|
value = value || [];
|
||||||
|
if (length(value) != length(expected))
|
||||||
|
fail(label + " length mismatch: " + sprintf("%J", value));
|
||||||
|
for (let i = 0; i < length(expected); i++)
|
||||||
|
if (value[i] != expected[i])
|
||||||
|
fail(label + " mismatch: " + sprintf("%J", value));
|
||||||
|
}
|
||||||
|
let cfg = json(fs.readfile(ARGV[0]));
|
||||||
|
let selector = outbound_by_tag(cfg, "proxy-out");
|
||||||
|
let urltest = outbound_by_tag(cfg, "proxy-urltest-ut_auto-out");
|
||||||
|
let priority = outbound_by_tag(cfg, "proxy-priority-pg_auto-out");
|
||||||
|
|
||||||
|
if (!selector) fail("missing proxy-out selector");
|
||||||
|
if (!urltest) fail("missing proxy-urltest-ut_auto-out outbound");
|
||||||
|
if (!priority) fail("missing proxy-priority-pg_auto-out outbound");
|
||||||
|
|
||||||
|
assert_array(urltest.outbounds, [ "🇳🇱 Amsterdam", "🇩🇪 Berlin" ], "URLTest outbounds must not include section-excluded RU server");
|
||||||
|
assert_array(priority.outbounds, [ "🇳🇱 Amsterdam", "🇩🇪 Berlin" ], "Priority outbounds must not include section-excluded RU server");
|
||||||
|
assert_array(selector.outbounds, [ "🇳🇱 Amsterdam", "🇩🇪 Berlin", "proxy-urltest-ut_auto-out", "proxy-priority-pg_auto-out" ], "Selector outbounds must not include section-excluded RU server");
|
||||||
|
|
||||||
|
if (selector.default != "proxy-urltest-ut_auto-out")
|
||||||
|
fail("selector default must be the urltest group");
|
||||||
|
' "$WORK_DIR/issue89-config.json" || fail "issue89 cascade exclusion regression"
|
||||||
|
|
||||||
printf 'dashboard server filter checks passed\n'
|
printf 'dashboard server filter checks passed\n'
|
||||||
|
|||||||
Reference in New Issue
Block a user