fix: prevent package removal during web update and fix zapret2 installation
- Fix package postrm scripts to strictly require \ to be 'remove' or 'purge' before running cleanup, preventing destructive cleanup when opkg runs postrm with empty arguments during reinstalls/upgrades. - In action.uc install_files, ensure tachyon backend package is installed before luci-app-tachyon to prevent opkg dependency removal races. - In action.uc install_zapret2, ensure ::1 localhost exists in /etc/hosts before package installation to prevent nftables IPv6 resolution errors, and cleanly stop/disable standalone zapret2 daemon. - In zapret2 provider common.uc and nfqueue runtime.uc, automatically resolve required blob binary payloads and default filter parameters for strategies. - In fe-app-tachyon, add 'access denied' / 'Доступ запрещён' to transient RPC error patterns and track install_version as self-update so rpcd reload during self-update does not abort the progress modal with an error. - In tests/package_lifecycle.sh, avoid grep -q in pipefail pipelines to prevent upstream SIGPIPE failures.
This commit is contained in:
+6
-1
@@ -159,9 +159,14 @@ define Package/tachyon/postrm
|
||||
[ "$$1" = "upgrade" ] && exit 0
|
||||
[ "$$1" != "remove" ] && [ "$$1" != "purge" ] && [ -n "$$1" ] && exit 0
|
||||
|
||||
if [ -f /var/run/tachyon/component-actions/action.lock ] || [ -f /tmp/run/tachyon/component-actions/action.lock ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
rm -f /www/cgi-bin/tachyon-agent /etc/hotplug.d/iface/99-tachyon-wan-monitor 2>/dev/null || true
|
||||
rm -f /usr/share/nftables.d/chain-pre/input/10-tachyon.nft 2>/dev/null || true
|
||||
rm -rf /var/run/tachyon* /tmp/tachyon* /tmp/sing-box /tmp/ai_doctor* /tmp/tg_* /tmp/warp_* 2>/dev/null || true
|
||||
rm -rf /tmp/ai_doctor* /tmp/tg_* /tmp/warp_* 2>/dev/null || true
|
||||
rm -rf /var/run/tachyon/section-cache /var/run/tachyon/ui-state 2>/dev/null || true
|
||||
[ -x /etc/init.d/firewall ] && /etc/init.d/firewall restart >/dev/null 2>&1 || true
|
||||
[ -x /etc/init.d/dnsmasq ] && /etc/init.d/dnsmasq restart >/dev/null 2>&1 || true
|
||||
|
||||
|
||||
@@ -1408,6 +1408,10 @@ function install_zapret2(action, target_tag) {
|
||||
if (pkg == null)
|
||||
action_fail(component, action, "Failed to download " + label + " package", current_version, release.version, "", release.release_url || "");
|
||||
|
||||
let hosts_content = read_file("/etc/hosts") || "";
|
||||
if (index(hosts_content, "::1") < 0)
|
||||
command_success("printf '\\n::1 localhost ip6-localhost ip6-loopback\\n' >> /etc/hosts");
|
||||
|
||||
if (!run_logged("Installing " + label + " package " + pkg.name, pkg_install_files_command([ pkg.file ])))
|
||||
action_fail(component, action, "Failed to install " + label + " package", current_version, pkg.version, "", release.release_url || "");
|
||||
|
||||
@@ -1418,8 +1422,11 @@ function install_zapret2(action, target_tag) {
|
||||
if (file_exists("/opt/zapret2"))
|
||||
command_status_from_args([ "chmod", "-R", "a+rX", "/opt/zapret2" ]);
|
||||
|
||||
command_success_from_args([ "killall", "-9", "nfqws2" ]);
|
||||
disable_standalone_service(component);
|
||||
command_status_from_args([ "nft", "delete", "table", "inet", "zapret2" ]);
|
||||
command_status_from_args([ "nft", "delete", "table", "ip", "zapret2" ]);
|
||||
command_status_from_args([ "nft", "delete", "table", "ip6", "zapret2" ]);
|
||||
restart_tachyon_after_successful_change();
|
||||
clear_version_caches();
|
||||
current_version = provider_package_version(runtime_module);
|
||||
@@ -2662,7 +2669,7 @@ function reinstall_tachyon() {
|
||||
(release.i18n_url != "" && !download_with_retry(release.i18n_url, i18n_file, release.i18n_name)))
|
||||
action_fail("tachyon", "reinstall", "Failed to download Tachyon release packages", TACHYON_VERSION, latest_version);
|
||||
|
||||
let reinstall_files = [ app_file, backend_file ];
|
||||
let reinstall_files = [ backend_file, app_file ];
|
||||
if (i18n_file != "")
|
||||
push(reinstall_files, i18n_file);
|
||||
if (!run_logged_retrying("Reinstalling Tachyon packages", pkg_install_files_command(reinstall_files, true)))
|
||||
@@ -2706,7 +2713,7 @@ function install_tachyon() {
|
||||
(release.i18n_url != "" && !download_with_retry(release.i18n_url, i18n_file, release.i18n_name)))
|
||||
action_fail("tachyon", "install", "Failed to download Tachyon release packages", TACHYON_VERSION, latest_version);
|
||||
|
||||
let install_files = [ app_file, backend_file ];
|
||||
let install_files = [ backend_file, app_file ];
|
||||
if (i18n_file != "")
|
||||
push(install_files, i18n_file);
|
||||
// Installing the same tag means a rebuild of the current release; opkg skips
|
||||
@@ -2750,7 +2757,7 @@ function install_tachyon_version(target_tag) {
|
||||
(release.i18n_url != "" && !download_with_retry(release.i18n_url, i18n_file, release.i18n_name)))
|
||||
action_fail("tachyon", "install_version", "Failed to download Tachyon release packages", TACHYON_VERSION, target_tag);
|
||||
|
||||
let install_files = [ app_file, backend_file ];
|
||||
let install_files = [ backend_file, app_file ];
|
||||
if (i18n_file != "")
|
||||
push(install_files, i18n_file);
|
||||
|
||||
|
||||
@@ -343,6 +343,10 @@ function supervisor_command(cfg, queue, raw_opt, child_pidfile) {
|
||||
let args = [ cfg.binary, "--qnum=" + as_string(queue) ];
|
||||
for (let arg in base_args(cfg))
|
||||
push(args, arg);
|
||||
if (type(cfg.prepare_strategy_args) == "function") {
|
||||
for (let extra in cfg.prepare_strategy_args(raw_opt))
|
||||
push(args, extra);
|
||||
}
|
||||
for (let word in strategy_words(raw_opt))
|
||||
push(args, word);
|
||||
|
||||
|
||||
@@ -12,6 +12,68 @@ function validator() {
|
||||
return validator_module;
|
||||
}
|
||||
|
||||
const KNOWN_BLOB_FILES = {
|
||||
tls_max: { file: "tls_clienthello_max_ru.bin", size: 654 },
|
||||
tls_google: { file: "tls_clienthello_www_google_com.bin", size: 681 },
|
||||
tls_gosuslugi: { file: "tls_clienthello_gosuslugi_ru.bin", size: 517 },
|
||||
tls_sber: { file: "tls_clienthello_sberbank_ru.bin", size: 517 },
|
||||
tls_iana: { file: "tls_clienthello_iana_org.bin", size: 517 },
|
||||
tls_vk: { file: "tls_clienthello_vk_com.bin", size: 517 },
|
||||
tls_onetrust: { file: "tls_clienthello_www_onetrust_com.bin", size: 664 },
|
||||
quic_google: { file: "quic_initial_www_google_com.bin", size: 1200 },
|
||||
quic_yt1: { file: "quic_initial_rr1---sn-xguxaxjvh-n8me_googlevideo_com_kyber_1.bin", size: 1230 },
|
||||
quic_vk: { file: "quic_initial_vk_com.bin", size: 1357 },
|
||||
stun_fake: { file: "stun.bin", size: 100 },
|
||||
discord_udp: { file: "stun.bin", size: 100 }
|
||||
};
|
||||
|
||||
function get_blob_dir() {
|
||||
let candidate_dirs = [
|
||||
getenv("ZAPRET2_PROVIDER_FILES_DIR") ? (getenv("ZAPRET2_PROVIDER_FILES_DIR") + "/fake") : null,
|
||||
"/opt/zapret2/files/fake",
|
||||
"/usr/share/zapret2/files/fake",
|
||||
"/etc/zapret2/files/fake",
|
||||
"/opt/zapret/files/fake",
|
||||
"/usr/share/zapret/files/fake"
|
||||
];
|
||||
for (let d in candidate_dirs) {
|
||||
if (d && fs.stat(d) != null) return d;
|
||||
}
|
||||
return "/opt/zapret2/files/fake";
|
||||
}
|
||||
|
||||
function resolve_blobs(args_str) {
|
||||
if (!args_str || args_str == "") return [];
|
||||
let bdir = get_blob_dir();
|
||||
let result = [];
|
||||
for (let name, info in KNOWN_BLOB_FILES) {
|
||||
if ((index(args_str, "blob=" + name) >= 0 || index(args_str, "seqovl_pattern=" + name) >= 0) &&
|
||||
index(args_str, "--blob=" + name + ":") < 0) {
|
||||
let blob_path = bdir + "/" + info.file;
|
||||
if (fs.stat(blob_path) != null || fs.stat("/opt/zapret2/files/fake/" + info.file) != null) {
|
||||
let actual_path = fs.stat(blob_path) != null ? blob_path : ("/opt/zapret2/files/fake/" + info.file);
|
||||
push(result, sprintf("--blob=%s:@%s", name, actual_path));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function prepare_strategy_args(raw_opt) {
|
||||
let raw_str = as_string(raw_opt);
|
||||
let extra_args = resolve_blobs(raw_str);
|
||||
let filter_prefix = [];
|
||||
if (index(raw_str, "--filter-tcp") < 0 && index(raw_str, "--filter-l7") < 0) {
|
||||
push(filter_prefix, "--filter-tcp=443");
|
||||
push(filter_prefix, "--filter-l7=tls");
|
||||
push(filter_prefix, "--payload=tls_client_hello");
|
||||
}
|
||||
let words = [];
|
||||
for (let arg in extra_args) push(words, arg);
|
||||
for (let f in filter_prefix) push(words, f);
|
||||
return words;
|
||||
}
|
||||
|
||||
function config(ctx) {
|
||||
let runtime_constants = (ctx && ctx.constants) || constants;
|
||||
let lib_dir = (ctx && ctx.lib_dir) || LIB_DIR;
|
||||
@@ -111,7 +173,8 @@ function config(ctx) {
|
||||
hostlist_dir: "",
|
||||
status_label: "zapret2",
|
||||
check_prefix: "zapret2",
|
||||
base_args
|
||||
base_args,
|
||||
prepare_strategy_args
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -226,8 +226,6 @@ function prerm_cleanup(action) {
|
||||
// Kill any remaining tachyon processes, minus this hook's own ancestors.
|
||||
system(kill_matching_command("-F '" + BIN_PATH + "'"));
|
||||
restore_dnsmasq_if_needed();
|
||||
if (action == "remove")
|
||||
remove_managed_sing_box();
|
||||
}
|
||||
remove_rt_tables_entry(); // best-effort
|
||||
return true;
|
||||
|
||||
@@ -47,7 +47,11 @@ const RT_TABLE_NAME = getenv("RT_TABLE_NAME") || "tachyon";
|
||||
const NFT_FAKEIP_MARK = getenv("NFT_FAKEIP_MARK") || "0x04000000";
|
||||
const SB_DNS_INBOUND_ADDRESS = getenv("SB_DNS_INBOUND_ADDRESS") || "127.0.0.42";
|
||||
const ZAPRET_PROVIDER_NFQWS_BIN = getenv("ZAPRET_PROVIDER_NFQWS_BIN") || "/opt/zapret/nfq/nfqws";
|
||||
const ZAPRET2_PROVIDER_NFQWS2_BIN = getenv("ZAPRET2_PROVIDER_NFQWS2_BIN") || "/opt/zapret2/nfq2/nfqws2";
|
||||
let default_zapret2_bin = "/opt/zapret2/nfq2/nfqws2";
|
||||
for (let b in [ "/opt/zapret2/nfq2/nfqws2", "/opt/zapret2/nfq/nfqws2", "/opt/zapret2/nfqws2", "/usr/bin/nfqws2" ]) {
|
||||
if (fs.stat(b) != null) { default_zapret2_bin = b; break; }
|
||||
}
|
||||
const ZAPRET2_PROVIDER_NFQWS2_BIN = getenv("ZAPRET2_PROVIDER_NFQWS2_BIN") || default_zapret2_bin;
|
||||
const BYEDPI_BIN = getenv("BYEDPI_BIN") || "/usr/bin/ciadpi";
|
||||
|
||||
let read_json_file = common.read_json_file;
|
||||
|
||||
@@ -48,7 +48,11 @@ const SB_SERVICE_MIXED_INBOUND_PORT = getenv("SB_SERVICE_MIXED_INBOUND_PORT") ||
|
||||
const SB_VARIANT_STATE_FILE = getenv("SB_VARIANT_STATE_FILE") || "/etc/tachyon/sing-box-variant";
|
||||
const SB_VERSION_STATE_FILE = getenv("SB_VERSION_STATE_FILE") || "/etc/tachyon/sing-box-version";
|
||||
const ZAPRET_PROVIDER_NFQWS_BIN = getenv("ZAPRET_PROVIDER_NFQWS_BIN") || "/opt/zapret/nfq/nfqws";
|
||||
const ZAPRET2_PROVIDER_NFQWS2_BIN = getenv("ZAPRET2_PROVIDER_NFQWS2_BIN") || "/opt/zapret2/nfq2/nfqws2";
|
||||
let default_zapret2_bin = "/opt/zapret2/nfq2/nfqws2";
|
||||
for (let b in [ "/opt/zapret2/nfq2/nfqws2", "/opt/zapret2/nfq/nfqws2", "/opt/zapret2/nfqws2", "/usr/bin/nfqws2" ]) {
|
||||
if (fs.stat(b) != null) { default_zapret2_bin = b; break; }
|
||||
}
|
||||
const ZAPRET2_PROVIDER_NFQWS2_BIN = getenv("ZAPRET2_PROVIDER_NFQWS2_BIN") || default_zapret2_bin;
|
||||
const BYEDPI_BIN = getenv("BYEDPI_BIN") || "/usr/bin/ciadpi";
|
||||
|
||||
function read_stdin() {
|
||||
|
||||
Reference in New Issue
Block a user