From b9c5dc7236ff6e44bc2cda2be858a566d66fb452 Mon Sep 17 00:00:00 2001 From: action Date: Sat, 17 Oct 2026 22:50:00 +0800 Subject: [PATCH] update 2026-10-17 22:50:00 --- luci-app-amlogic/Makefile | 2 +- .../resources/view/amlogic/armcpu.js | 1 - .../resources/view/amlogic/config.js | 59 ++++++---- .../root/usr/share/passwall/app.sh | 3 - .../root/usr/share/passwall/lease2hosts.sh | 2 +- .../cbi/passwall2/client/type/1_sing-box.lua | 10 ++ .../cbi/passwall2/client/type/2_xray.lua | 10 ++ luci-app-passwall2/luasrc/passwall2/api.lua | 7 +- .../luasrc/passwall2/util_sing-box.lua | 4 +- .../luasrc/passwall2/util_xray.lua | 4 +- luci-app-passwall2/po/fa/passwall2.po | 13 ++- luci-app-passwall2/po/ru/passwall2.po | 13 ++- luci-app-passwall2/po/zh-cn/passwall2.po | 10 +- luci-app-passwall2/po/zh-tw/passwall2.po | 13 ++- .../root/usr/share/passwall2/app.sh | 28 +++-- .../root/usr/share/passwall2/lease2hosts.sh | 90 +++++++++++---- .../usr/share/passwall2/socks_auto_switch.sh | 106 +++++++++--------- .../root/etc/init.d/shadowsocksr | 6 +- luci-app-ssr-plus/root/usr/bin/ssr-monitor | 12 +- 19 files changed, 262 insertions(+), 131 deletions(-) diff --git a/luci-app-amlogic/Makefile b/luci-app-amlogic/Makefile index 64824a23..dcec7db2 100644 --- a/luci-app-amlogic/Makefile +++ b/luci-app-amlogic/Makefile @@ -22,7 +22,7 @@ PKG_NAME:=luci-app-amlogic # DD = day (01 = 1st) # NN = daily release sequence (01 = first release of the day, 02 = second, ...) # Example below: 26.10.0101 = October 1, 2026, 1st release of the day -PKG_VERSION:=26.10.1501 +PKG_VERSION:=26.10.1603 # PKG_RELEASE marks the LuCI variant; onekey-install.sh relies on it (do NOT bump) # 1 = Lua version (lua branch) → tag: 26.10.0101 # 2 = JS version (main branch) → tag: 26.10.0101-js diff --git a/luci-app-amlogic/htdocs/luci-static/resources/view/amlogic/armcpu.js b/luci-app-amlogic/htdocs/luci-static/resources/view/amlogic/armcpu.js index 217e3ad3..d64898bb 100644 --- a/luci-app-amlogic/htdocs/luci-static/resources/view/amlogic/armcpu.js +++ b/luci-app-amlogic/htdocs/luci-static/resources/view/amlogic/armcpu.js @@ -43,7 +43,6 @@ return view.extend({ const m = new form.Map('amlogic', _('CPU Freq Settings'), _('Set CPU Scaling Governor to Max Performance or Balance Mode')); const s = m.section(form.NamedSection, 'armcpu', 'settings'); - s.anonymous = true; // Render an independent tab + form options per CPU cluster (big/little). policies.forEach(function (p) { diff --git a/luci-app-amlogic/htdocs/luci-static/resources/view/amlogic/config.js b/luci-app-amlogic/htdocs/luci-static/resources/view/amlogic/config.js index 29148b46..09604560 100644 --- a/luci-app-amlogic/htdocs/luci-static/resources/view/amlogic/config.js +++ b/luci-app-amlogic/htdocs/luci-static/resources/view/amlogic/config.js @@ -17,7 +17,7 @@ const callPlatform = rpc.declare({ object: 'luci.amlogic', method: 'platform_inf // Query runtime state; kernel_release is used to derive default kernel tag and branch. const callState = rpc.declare({ object: 'luci.amlogic', method: 'state' }); -// This page uses its own Save button; hide LuCI's default Save/Apply/Reset. +// Saves go through LuCI's default footer buttons (Save & Apply / Save / Reset). return view.extend({ // Load platform info + state in parallel, along with the UCI config (we will read/write it). load: function () { @@ -43,7 +43,17 @@ return view.extend({ _('You can customize the github.com download repository of OpenWrt files and kernels in [Online Download Update].') + '
' + _('Tip: The same files as the current OpenWrt system\'s BOARD (such as rock5b) and kernel (such as 5.10) will be downloaded.')); const o = m.section(form.NamedSection, 'config', 'amlogic'); - o.anonymous = true; + + // Load the derived default ourselves whenever the stored value is blank. + const orDefault = function (option, defval) { + option.default = defval; + option.load = function (section_id) { + const v = uci.get(this.uciconfig ?? 'amlogic', + this.ucisection ?? section_id, + this.ucioption ?? this.option); + return (v == null || v === '') ? defval : v; + }; + }; // 1. Display device platform const dev = o.option(form.DummyValue, 'mydevice', _('Current Device:'), @@ -73,10 +83,11 @@ return view.extend({ suffix.rmempty = false; // 5. Kernel download repository - const kpath = o.option(form.ListValue, 'amlogic_kernel_path', + const kpath = o.option(form.Value, 'amlogic_kernel_path', _('Kernel download repository:'), _('Set the kernel files download repository on github.com in [Online Download Update].')); kpath.value('https://github.com/ophub/kernel'); + kpath.value('https://github.com/breakingbadboy/OpenWrt'); kpath.default = 'https://github.com/ophub/kernel'; kpath.rmempty = false; @@ -93,32 +104,38 @@ return view.extend({ knownTags.kernel_flippy = 'kernel_flippy [Mainline Stable Kernel by Flippy]'; knownTags.kernel_beta = 'kernel_beta [Beta Kernel]'; } - // Determine default tag from saved config or kernel_release uname string. - let kernelTagDefault = uci.get('amlogic', 'config', 'amlogic_kernel_tags') || ''; - if (!kernelTagDefault) { - const u = state.kernel_release || ''; - if (u.indexOf('-rk3588') >= 0) kernelTagDefault = 'kernel_rk3588'; - else if (u.indexOf('-rk35xx') >= 0) kernelTagDefault = 'kernel_rk35xx'; - else if (u.indexOf('-beta') >= 0) kernelTagDefault = 'kernel_beta'; - else kernelTagDefault = 'kernel_stable'; - } - const ktags = o.option(form.ListValue, 'amlogic_kernel_tags', + // Derive the default tag from the kernel_release uname string. A value already + // saved in UCI wins; orDefault() below only kicks in when that value is blank. + const uname = state.kernel_release || ''; + let kernelTagDefault = 'kernel_stable'; + if (uname.indexOf('-rk3588') >= 0) kernelTagDefault = 'kernel_rk3588'; + else if (uname.indexOf('-rk35xx') >= 0) kernelTagDefault = 'kernel_rk35xx'; + else if (uname.indexOf('-beta') >= 0) kernelTagDefault = 'kernel_beta'; + const ktags = o.option(form.Value, 'amlogic_kernel_tags', _('Kernel download tags:'), _('Set the kernel files download tags on github.com in [Online Download Update].')); Object.keys(knownTags).forEach(function (k) { ktags.value(k, _(knownTags[k])); }); + // kernel_beta is only offered for ophub/kernel, but a beta kernel may still be + // running, so keep the derived value selectable even when it is not listed. if (!knownTags[kernelTagDefault]) ktags.value(kernelTagDefault, kernelTagDefault); - ktags.default = kernelTagDefault; + orDefault(ktags, kernelTagDefault); ktags.rmempty = false; // 7. Kernel branch - const kbranch = o.option(form.ListValue, 'amlogic_kernel_branch', + const kbranches = ['5.10', '5.15', '6.1', '6.6', '6.12', '6.18']; + const kbranch = o.option(form.Value, 'amlogic_kernel_branch', _('Set version branch:'), _('Set the version branch of the OpenWrt files and kernel selected in [Online Download Update].')); - ['5.10', '5.15', '6.1', '6.6', '6.12', '6.18'].forEach(function (b) { - kbranch.value(b, _(b)); + + // Extract the major.minor version from the kernel uname string to determine the default branch. + const km = uname.match(/^(\d+\.\d+)/); + const kbranchDefault = km ? km[1] : kbranches[0]; + // If the derived default branch is not in the list, add it so it can be selected. + if (kbranches.indexOf(kbranchDefault) < 0) kbranches.push(kbranchDefault); + kbranches.forEach(function (b) { + kbranch.value(b, b); }); - const m2 = (state.kernel_release || '').match(/^(\d+\.\d+)/); - kbranch.default = m2 ? m2[1] : '5.10'; + orDefault(kbranch, kbranchDefault); kbranch.rmempty = false; // 8. Plugin branch @@ -140,14 +157,14 @@ return view.extend({ fcfg.default = '1'; fcfg.rmempty = false; - // 9. Write bootloader + // 10. Write bootloader const wb = o.option(form.Flag, 'amlogic_write_bootloader', _('Auto write bootloader:'), _('[Recommended choice] Set whether to auto write bootloader during install and update OpenWrt.')); wb.default = '0'; wb.rmempty = false; - // 10. Shared partition fs type + // 11. Shared partition fs type const fst = o.option(form.ListValue, 'amlogic_shared_fstype', _('Set the file system type:'), _('[Default ext4] Set the file system type of the shared partition (/mnt/mmcblk*p4) when install OpenWrt.')); diff --git a/luci-app-passwall/root/usr/share/passwall/app.sh b/luci-app-passwall/root/usr/share/passwall/app.sh index 957b99ed..c50a1ecb 100755 --- a/luci-app-passwall/root/usr/share/passwall/app.sh +++ b/luci-app-passwall/root/usr/share/passwall/app.sh @@ -1814,9 +1814,6 @@ stop() { [ -n "${bak_bridge_nf_ip6t}" ] && sysctl -w net.bridge.bridge-nf-call-ip6tables=${bak_bridge_nf_ip6t} >/dev/null 2>&1 } rm -rf $TMP_PATH - rm -f ${LOCK_PATH}/${CONFIG}_socks_auto_switch* - rm -f ${LOCK_PATH}/${CONFIG}_lease2hosts* - rm -f ${LOCK_PATH}/${CONFIG}_monitor* echolog "清空并关闭相关程序和缓存完成。" exit 0 } diff --git a/luci-app-passwall/root/usr/share/passwall/lease2hosts.sh b/luci-app-passwall/root/usr/share/passwall/lease2hosts.sh index 3d7d39bd..0296b851 100755 --- a/luci-app-passwall/root/usr/share/passwall/lease2hosts.sh +++ b/luci-app-passwall/root/usr/share/passwall/lease2hosts.sh @@ -93,6 +93,6 @@ while true; do rm -f "$TMP_FILE" fi - sleep 60 + sleep 60 9>&- done 2>/dev/null diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/1_sing-box.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/1_sing-box.lua index b902a483..86c4f086 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/1_sing-box.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/1_sing-box.lua @@ -498,6 +498,16 @@ if singbox_tags:find("with_quic") then o = s:option(Value, "hysteria2_down_mbps", translate("Max download Mbps")) o:depends({ protocol = "hysteria2" }) + o = s:option(Value, "hysteria2_stream_recv_win", translate("QUIC stream receive window") .. " (MB)") + o.datatype = "range(1,1000)" + o.placeholder = "8" + o:depends({ protocol = "hysteria2" }) + + o = s:option(Value, "hysteria2_conn_recv_win", translate("QUIC connection receive window") .. " (MB)") + o.datatype = "range(1,1000)" + o.placeholder = "20" + o:depends({ protocol = "hysteria2" }) + o = s:option(Value, "hysteria2_idle_timeout", translate("Idle Timeout"), translate("Units:seconds") .. " (4~120)") o.datatype = "range(4,120)" o:depends({ protocol = "hysteria2"}) diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/2_xray.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/2_xray.lua index 338081b8..88840957 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/2_xray.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/2_xray.lua @@ -403,6 +403,16 @@ o:depends({ protocol = "hysteria2" }) o = s:option(Value, "hysteria2_down_mbps", translate("Max download Mbps")) o:depends({ protocol = "hysteria2" }) +o = s:option(Value, "hysteria2_stream_recv_win", translate("QUIC stream receive window") .. " (MB)") +o.datatype = "range(1,1000)" +o.placeholder = "8" +o:depends({ protocol = "hysteria2" }) + +o = s:option(Value, "hysteria2_conn_recv_win", translate("QUIC connection receive window") .. " (MB)") +o.datatype = "range(1,1000)" +o.placeholder = "20" +o:depends({ protocol = "hysteria2" }) + o = s:option(Value, "hysteria2_idle_timeout", translate("Idle Timeout"), translate("Units:seconds") .. " (4~120)") o.datatype = "range(4,120)" o:depends({ protocol = "hysteria2"}) diff --git a/luci-app-passwall2/luasrc/passwall2/api.lua b/luci-app-passwall2/luasrc/passwall2/api.lua index 25a724ce..8adf54b1 100644 --- a/luci-app-passwall2/luasrc/passwall2/api.lua +++ b/luci-app-passwall2/luasrc/passwall2/api.lua @@ -449,9 +449,10 @@ function repeat_exist(table, value) end function remove(...) - for index, value in ipairs({...}) do - if value and #value > 0 and value ~= "/" then - sys.call(string.format("rm -rf %s", value)) + for i = 1, select("#", ...) do + local value = select(i, ...) + if type(value) == "string" and #value > 0 and value ~= "/" then + sys.call(string.format("rm -rf -- %s", value)) end end end diff --git a/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua b/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua index 651f6919..5f6e8b27 100644 --- a/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua +++ b/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua @@ -635,7 +635,9 @@ function gen_outbound(flag, node, tag, proxy_table) t = tonumber(tostring(t or "0"):match("^%d+")) return (t and t >= 2 and t <= 60) and t .. "s" or nil end)(node.hysteria2_keep_alive_period), - disable_path_mtu_discovery = version_ge_1_14_0 and (tonumber(node.hysteria2_disable_mtu_discovery) == 1) or nil, + stream_receive_window = tonumber(node.hysteria2_stream_recv_win) and tonumber(node.hysteria2_stream_recv_win) .. " MB" or nil, + connection_receive_window = tonumber(node.hysteria2_conn_recv_win) and tonumber(node.hysteria2_conn_recv_win) .. " MB" or nil, + disable_path_mtu_discovery = version_ge_1_14_0 and (node.hysteria2_disable_mtu_discovery == "1") or nil, tls = tls, realm = node.hysteria2_realms and (function() result.server = nil diff --git a/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/luci-app-passwall2/luasrc/passwall2/util_xray.lua index 8a79f385..11d8eb83 100644 --- a/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -400,7 +400,9 @@ function gen_outbound(flag, node, tag, proxy_table) t = tonumber(tostring(t or "0"):match("^%d+")) return (t and t >= 2 and t <= 60) and t or nil end)(node.hysteria2_keep_alive_period), - disablePathMTUDiscovery = tonumber(node.hysteria2_disable_mtu_discovery) == 1 + disablePathMTUDiscovery = node.hysteria2_disable_mtu_discovery == "1", + initStreamReceiveWindow = tonumber(node.hysteria2_stream_recv_win) and tonumber(node.hysteria2_stream_recv_win)*1048576 or nil, + initConnectionReceiveWindow = tonumber(node.hysteria2_conn_recv_win) and tonumber(node.hysteria2_conn_recv_win)*1048576 or nil, } end if fragment and fragment_table and ({raw=1, ws=1, httpupgrade=1, grpc=1, xhttp=1})[TP] then diff --git a/luci-app-passwall2/po/fa/passwall2.po b/luci-app-passwall2/po/fa/passwall2.po index 1adb75d6..3aac913a 100644 --- a/luci-app-passwall2/po/fa/passwall2.po +++ b/luci-app-passwall2/po/fa/passwall2.po @@ -2219,8 +2219,14 @@ msgstr "تشخیص تغییر وضعیت سوکت‌ها: تغییر وضعیت msgid "Socks switch detection: Port [%s] [%s:[%s]] abnormal." msgstr "تشخیص وضعیت سوئیچ: پورت [%s] [%s:[%s]] غیرعادی است." -msgid "Socks switch detection: Port [%s] all nodes are unavailable!" -msgstr "تشخیص تغییر وضعیت سوئیچ: در پورت [%s]، تمام گره‌ها در دسترس نیستند!" +msgid "Socks switch detection: Port [%s] all nodes are unavailable or switching failed!" +msgstr "بررسی تغییر گره SOCKS: پورت [%s]، همه گره‌ها در دسترس نیستند یا تغییر گره ناموفق بود!" + +msgid "Socks switch detection: Port [%s] node switch failed, continue trying other nodes!" +msgstr "بررسی تغییر گره SOCKS: پورت [%s]، تغییر گره ناموفق بود؛ تلاش با گره‌های دیگر ادامه دارد!" + +msgid "Socks switch detection: Port [%s] failed to restore the primary node!" +msgstr "بررسی تغییر گره SOCKS: پورت [%s]، بازیابی گره اصلی ناموفق بود!" msgid "Socks switch detection: Port [%s] Unknown error." msgstr "تشخیص وضعیت سوئیچ جوراب: پورت [%s] خطای ناشناخته." @@ -2486,6 +2492,9 @@ msgstr "فهرست مجموعه‌های رمز پشتیبانی‌شده را msgid "This username already exists." msgstr "این نام کاربری از قبل وجود دارد." +msgid "Update Options" +msgstr "گزینه‌های به‌روزرسانی" + msgid "MASQUE Path" msgstr "مسیر MASQUE" diff --git a/luci-app-passwall2/po/ru/passwall2.po b/luci-app-passwall2/po/ru/passwall2.po index d734ded3..85588a2b 100644 --- a/luci-app-passwall2/po/ru/passwall2.po +++ b/luci-app-passwall2/po/ru/passwall2.po @@ -2220,8 +2220,14 @@ msgstr "Обнаружение переключения соединений: п msgid "Socks switch detection: Port [%s] [%s:[%s]] abnormal." msgstr "Обнаружено переключение Socks: порт [%s] [%s:[%s]] работает некорректно." -msgid "Socks switch detection: Port [%s] all nodes are unavailable!" -msgstr "Обнаружено переключение коммутатора: порт [%s], все узлы недоступны!" +msgid "Socks switch detection: Port [%s] all nodes are unavailable or switching failed!" +msgstr "Проверка переключения SOCKS: порт [%s], все узлы недоступны или переключение не удалось!" + +msgid "Socks switch detection: Port [%s] node switch failed, continue trying other nodes!" +msgstr "Проверка переключения SOCKS: порт [%s], переключить узел не удалось, пробуем другие узлы!" + +msgid "Socks switch detection: Port [%s] failed to restore the primary node!" +msgstr "Проверка переключения SOCKS: порт [%s], не удалось восстановить основной узел!" msgid "Socks switch detection: Port [%s] Unknown error." msgstr "Обнаружение переключения разъема: порт [%s], неизвестная ошибка." @@ -2487,6 +2493,9 @@ msgstr "Задает список поддерживаемых наборов ш msgid "This username already exists." msgstr "Это имя пользователя уже существует." +msgid "Update Options" +msgstr "Параметры обновления" + msgid "MASQUE Path" msgstr "Путь MASQUE" diff --git a/luci-app-passwall2/po/zh-cn/passwall2.po b/luci-app-passwall2/po/zh-cn/passwall2.po index 1c4de240..4cda9e08 100644 --- a/luci-app-passwall2/po/zh-cn/passwall2.po +++ b/luci-app-passwall2/po/zh-cn/passwall2.po @@ -2205,8 +2205,14 @@ msgstr "Socks切换检测:端口 [%s] 节点切换完毕!" msgid "Socks switch detection: Port [%s] [%s:[%s]] abnormal." msgstr "Socks切换检测:端口 [%s] 异常。" -msgid "Socks switch detection: Port [%s] all nodes are unavailable!" -msgstr "Socks切换检测:端口 [%s] 所有节点均不可用!" +msgid "Socks switch detection: Port [%s] all nodes are unavailable or switching failed!" +msgstr "Socks切换检测:端口 [%s] 所有节点均不可用或切换失败!" + +msgid "Socks switch detection: Port [%s] node switch failed, continue trying other nodes!" +msgstr "Socks切换检测:端口 [%s] 节点切换失败,继续尝试其他节点!" + +msgid "Socks switch detection: Port [%s] failed to restore the primary node!" +msgstr "Socks切换检测:端口 [%s] 恢复主节点失败!" msgid "Socks switch detection: Port [%s] Unknown error." msgstr "Socks切换检测:端口 [%s] 未知错误。" diff --git a/luci-app-passwall2/po/zh-tw/passwall2.po b/luci-app-passwall2/po/zh-tw/passwall2.po index e1bede5b..9cdc756b 100644 --- a/luci-app-passwall2/po/zh-tw/passwall2.po +++ b/luci-app-passwall2/po/zh-tw/passwall2.po @@ -2211,8 +2211,14 @@ msgstr "Socks切換偵測:連接埠 [%s] 節點切換完畢!" msgid "Socks switch detection: Port [%s] [%s:[%s]] abnormal." msgstr "Socks切換偵測:連接埠 [%s] 異常。" -msgid "Socks switch detection: Port [%s] all nodes are unavailable!" -msgstr "Socks切換偵測:連接埠 [%s] 所有節點均不可用!" +msgid "Socks switch detection: Port [%s] all nodes are unavailable or switching failed!" +msgstr "Socks切換偵測:連接埠 [%s] 所有節點均不可用或切換失敗!" + +msgid "Socks switch detection: Port [%s] node switch failed, continue trying other nodes!" +msgstr "Socks切換偵測:連接埠 [%s] 節點切換失敗,繼續嘗試其他節點!" + +msgid "Socks switch detection: Port [%s] failed to restore the primary node!" +msgstr "Socks切換偵測:連接埠 [%s] 恢復主節點失敗!" msgid "Socks switch detection: Port [%s] Unknown error." msgstr "Socks切換偵測:連接埠 [%s] 未知錯誤。" @@ -2478,6 +2484,9 @@ msgstr "配置支援的密碼套件列表。" msgid "This username already exists." msgstr "該用戶名已存在。" +msgid "Update Options" +msgstr "更新選項" + msgid "MASQUE Path" msgstr "MASQUE 路徑" diff --git a/luci-app-passwall2/root/usr/share/passwall2/app.sh b/luci-app-passwall2/root/usr/share/passwall2/app.sh index d2fff4e0..29956404 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/app.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/app.sh @@ -380,7 +380,7 @@ run_socks() { if [ -n "$server_host" ] && [ -n "$server_port" ]; then check_host $server_host [ $? != 0 ] && { - log 1 "$(i18n "Socks node: [%s]%s is an invalid server address and cannot be started!" "${$remarks}" "${server_host}")" + log 1 "$(i18n "Socks node: [%s]%s is an invalid server address and cannot be started!" "${remarks}" "${server_host}")" return 1 } tmp="${server_host}:${server_port}" @@ -553,9 +553,12 @@ socks_node_switch() { local http_config_file="${flag}_http.json" LOG_FILE="/dev/null" run_socks flag=$flag node=$new_node bind=$bind socks_port=$port config_file=$config_file http_port=$http_port http_config_file=$http_config_file log_file=$log_file + sleep 2s + [ "$(check_port_exists "$port" tcp)" = "0" ] && return 1 set_cache_var "${flag}" "$new_node" local USE_TABLES=$(get_cache_var "USE_TABLES") [ -n "$USE_TABLES" ] && source $APP_PATH/${USE_TABLES}.sh filter_direct_node_list + return 0 } } @@ -579,11 +582,15 @@ start_socks() { [ "$log" == "0" ] && log_file="" local http_port=$(config_n_get $id http_port 0) local http_config_file="${id}_http.json" - run_socks flag=$id node=$node bind=$bind socks_port=$port config_file=$config_file http_port=$http_port http_config_file=$http_config_file log_file=$log_file + local enable_autoswitch=$(config_n_get $id enable_autoswitch 0) + if [ "$enable_autoswitch" = "1" ]; then + NO_REC_PROCESS=1 $APP_PATH/app.sh run_socks flag=$id node=$node bind=$bind socks_port=$port config_file=$config_file http_port=$http_port http_config_file=$http_config_file log_file=$log_file + else + run_socks flag=$id node=$node bind=$bind socks_port=$port config_file=$config_file http_port=$http_port http_config_file=$http_config_file log_file=$log_file + fi set_cache_var "${id}" "$node" # Auto switch logic - local enable_autoswitch=$(config_n_get $id enable_autoswitch 0) [ "$enable_autoswitch" = "1" ] && { $APP_PATH/socks_auto_switch.sh ${id} > /dev/null 2>&1 & } done } @@ -619,6 +626,9 @@ start_crontab() { return } + local setsid_cmd="" + command -v setsid >/dev/null 2>&1 && setsid_cmd="setsid " + stop_week_mode=$(config_n_get @global_delay[0] stop_week_mode) stop_time_mode=$(config_n_get @global_delay[0] stop_time_mode) if [ -n "$stop_week_mode" ]; then @@ -626,7 +636,7 @@ start_crontab() { stop_time_mm=$(echo $stop_time_mode | awk -F ':' '{print $2}') local t="$stop_time_mm $stop_time_hh * * $stop_week_mode" [ "$stop_week_mode" = "7" ] && t="$stop_time_mm $stop_time_hh * * *" - echo "$t /etc/init.d/$CONFIG stop cron > /dev/null 2>&1 &" >>/etc/crontabs/root + echo "$t ${setsid_cmd}/etc/init.d/$CONFIG stop cron > /dev/null 2>&1 &" >>/etc/crontabs/root log_i18n 0 "Scheduled tasks: Auto stop service." fi @@ -637,7 +647,7 @@ start_crontab() { start_time_mm=$(echo $start_time_mode | awk -F ':' '{print $2}') local t="$start_time_mm $start_time_hh * * $start_week_mode" [ "$start_week_mode" = "7" ] && t="$start_time_mm $start_time_hh * * *" - echo "$t /etc/init.d/$CONFIG start cron > /dev/null 2>&1 &" >>/etc/crontabs/root + echo "$t ${setsid_cmd}/etc/init.d/$CONFIG start cron > /dev/null 2>&1 &" >>/etc/crontabs/root log_i18n 0 "Scheduled tasks: Auto start service." fi @@ -651,7 +661,7 @@ start_crontab() { if [ "$restart_week_mode" = "8" ]; then update_loop=1 else - echo "$t /etc/init.d/$CONFIG restart cron > /dev/null 2>&1 &" >>/etc/crontabs/root + echo "$t ${setsid_cmd}/etc/init.d/$CONFIG restart cron > /dev/null 2>&1 &" >>/etc/crontabs/root fi log_i18n 0 "Scheduled tasks: Auto restart service." fi @@ -666,7 +676,7 @@ start_crontab() { if [ "$rules_update_week_mode" = "8" ]; then update_loop=1 else - echo "$t lua $APP_PATH/rule_update.lua log all cron > /dev/null 2>&1 &" >>/etc/crontabs/root + echo "$t ${setsid_cmd}lua $APP_PATH/rule_update.lua log all cron > /dev/null 2>&1 &" >>/etc/crontabs/root fi log_i18n 0 "Scheduled tasks: Auto update rules." fi @@ -695,7 +705,7 @@ start_crontab() { if [ "$sub_update_week_mode" = "8" ]; then update_loop=1 else - echo "$t lua $APP_PATH/subscribe.lua start $cfgids cron > /dev/null 2>&1 &" >>/etc/crontabs/root + echo "$t ${setsid_cmd}lua $APP_PATH/subscribe.lua start $cfgids cron > /dev/null 2>&1 &" >>/etc/crontabs/root fi done rm -rf $TMP_SUB_PATH @@ -996,8 +1006,6 @@ stop() { [ -n "${bak_bridge_nf_ip6t}" ] && sysctl -w net.bridge.bridge-nf-call-ip6tables=${bak_bridge_nf_ip6t} >/dev/null 2>&1 } rm -rf $TMP_PATH - rm -f ${LOCK_PATH}/${CONFIG}_socks_auto_switch* - rm -f ${LOCK_PATH}/${CONFIG}_lease2hosts* rm -f ${LOCK_PATH}/${CONFIG}_monitor* log_i18n 0 "Clearing and closing related programs and cache complete." exit 0 diff --git a/luci-app-passwall2/root/usr/share/passwall2/lease2hosts.sh b/luci-app-passwall2/root/usr/share/passwall2/lease2hosts.sh index bf28f5e3..41da3ba6 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/lease2hosts.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/lease2hosts.sh @@ -1,17 +1,61 @@ #!/bin/sh -# dhcp.leases to hosts +# DHCP leases and static hosts to hosts + +. /lib/functions.sh . /usr/share/passwall2/utils.sh LOCK_FILE=${LOCK_PATH}/${CONFIG}_lease2hosts.lock -LEASE_FILE=$(uci -q get dhcp.@dnsmasq[0].leasefile || echo "/tmp/dhcp.leases") +DNSMASQ_LEASE_FILE=$(uci -q get 'dhcp.@dnsmasq[0].leasefile') +DNSMASQ_LEASE_FILE=${DNSMASQ_LEASE_FILE:-/tmp/dhcp.leases} +ODHCPD_LEASE_FILE=$(uci -q get dhcp.odhcpd.leasefile) +ODHCPD_LEASE_FILE=${ODHCPD_LEASE_FILE:-/tmp/odhcpd.leases} HOSTS_FILE="$TMP_PATH2/dhcp-hosts" TMP_FILE="/tmp/dhcp-hosts.tmp" -exec 99>"$LOCK_FILE" -flock -n 99 -if [ "$?" != 0 ]; then - exit 0 -fi +exec 9>"$LOCK_FILE" +flock -n 9 || exit 0 + +read_static_host() { + local name ip + config_get name "$1" name + config_get ip "$1" ip + [ -n "$name" ] && [ "$name" != "*" ] && [ -n "$ip" ] && [ "$ip" != "ignore" ] || return + printf '%s %s\n' "$ip" "$name" +} + +# Static DHCP configuration only needs to be read once at startup. +STATIC_HOSTS=$( + config_load dhcp + config_foreach read_static_host host +) + +read_odhcpd_leases() { + [ -f "$ODHCPD_LEASE_FILE" ] || return + awk -v now="$(date +%s)" ' + function valid_name(name) { + return name ~ /^[a-zA-Z0-9_][a-zA-Z0-9_.-]*$/ + } + # State records: # interface DUID IAID hostname expiry assigned length address/prefix ... + $1 == "#" { + if (NF < 9 || !valid_name($5) || ($6 != -1 && $6 <= now)) + next + # Only host addresses, never delegated IPv6 prefixes. + if (!(($4 == "ipv4" && $8 == 32) || ($4 != "ipv4" && $8 == 128))) + next + for (i = 9; i <= NF; i++) { + split($i, addr, "/") + print addr[1] " " $5 + } + next + } + # Older odhcpd versions also include hosts-format lines, with optional aliases. + NF >= 2 && $1 ~ /^[0-9a-fA-F:.]+$/ { + for (i = 2; i <= NF && $i !~ /^#/; i++) + if (valid_name($i)) + print $1 " " $i + } + ' "$ODHCPD_LEASE_FILE" +} reload_dnsmasq_pids() { local pidfile pid @@ -27,24 +71,28 @@ reload_dnsmasq_pids() { while true; do - if [ -f "$LEASE_FILE" ]; then - awk 'NF >= 4 && $4 != "*" {print $3" "$4}' "$LEASE_FILE" | sort > "$TMP_FILE" - if [ -s "$TMP_FILE" ]; then - if [ ! -f "$HOSTS_FILE" ] || ! cmp -s "$TMP_FILE" "$HOSTS_FILE"; then - mv "$TMP_FILE" "$HOSTS_FILE" - reload_dnsmasq_pids - else - rm -f "$TMP_FILE" - fi + { + [ -n "$STATIC_HOSTS" ] && printf '%s\n' "$STATIC_HOSTS" + if [ -f "$DNSMASQ_LEASE_FILE" ]; then + awk 'NF >= 4 && $4 != "*" {print $3" "$4}' "$DNSMASQ_LEASE_FILE" + fi + read_odhcpd_leases + } | sort -u > "$TMP_FILE" + if [ -s "$TMP_FILE" ]; then + if [ ! -f "$HOSTS_FILE" ] || ! cmp -s "$TMP_FILE" "$HOSTS_FILE"; then + mv "$TMP_FILE" "$HOSTS_FILE" + reload_dnsmasq_pids else - if [ -s "$HOSTS_FILE" ]; then - : > "$HOSTS_FILE" - reload_dnsmasq_pids - fi rm -f "$TMP_FILE" fi + else + if [ -s "$HOSTS_FILE" ]; then + : > "$HOSTS_FILE" + reload_dnsmasq_pids + fi + rm -f "$TMP_FILE" fi - sleep 60 + sleep 60 9>&- done 2>/dev/null diff --git a/luci-app-passwall2/root/usr/share/passwall2/socks_auto_switch.sh b/luci-app-passwall2/root/usr/share/passwall2/socks_auto_switch.sh index 634c276a..409ab956 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/socks_auto_switch.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/socks_auto_switch.sh @@ -3,11 +3,9 @@ . /usr/share/passwall2/utils.sh APP_FILE=${APP_PATH}/app.sh -flag=0 - check_process() { while busybox pgrep -af "${CONFIG}/" | grep -E 'app\.sh.*(start|stop)|nftables\.sh|iptables\.sh|subscribe\.lua' >/dev/null; do - sleep 6s + sleep 6s 8>&- 9>&- done } @@ -25,19 +23,21 @@ test_url() { fi [ "$curl_retry_all_errors" = "1" ] && extra_params="--retry-all-errors ${extra_params}" - local max_time=$((timeout * (try + 1) + try + 3)) + local max_time=$((timeout + 3)) + local retry_max_time=$((max_time * (try + 1) + try)) curl_test() { - /usr/bin/curl -skIL -o /dev/null ${extra_params} --max-time ${max_time} --connect-timeout ${timeout} --retry ${try} --retry-delay 1 -w "%{http_code}" "$url" + /usr/bin/curl -skIL -o /dev/null ${extra_params} --max-time ${max_time} --connect-timeout ${timeout} --retry ${try} --retry-delay 1 --retry-max-time ${retry_max_time} -w "%{http_code}" "$url" 8>&- 9>&- } - local status=$(curl_test) + local status + status=$(curl_test) || status=000 [ "$status" = "204" ] && status=200 if [ "$status" = "200" ] && [ "$repeat" = "1" ]; then - sleep 3s - status=$(curl_test) + sleep 3s 8>&- 9>&- + status=$(curl_test) || status=000 [ "$status" = "204" ] && status=200 fi - echo $status + printf '%s' "$status" } test_proxy() { @@ -51,7 +51,7 @@ test_proxy() { result=1 else result=2 - ping -c 3 -W 1 223.5.5.5 > /dev/null 2>&1 + ping -c 3 -W 1 223.5.5.5 > /dev/null 2>&1 8>&- 9>&- [ $? -eq 0 ] && { result=1 } @@ -62,24 +62,31 @@ test_proxy() { test_node() { local node_id=$1 - local _type=$(echo $(config_n_get ${node_id} type) | tr 'A-Z' 'a-z') - [ -n "${_type}" ] && { - check_process - local _tmp_port=$(get_new_port 48800 tcp,udp) - NO_REC_PROCESS=1 $APP_FILE run_socks flag="test_node_${node_id}" node=${node_id} bind=127.0.0.1 socks_port=${_tmp_port} config_file=test_node_${node_id}.json - sleep 2s - local curlx="socks5h://127.0.0.1:${_tmp_port}" - local _proxy_status=$(test_url "${probe_url}" ${retry_num} ${connect_timeout} "-x $curlx" 1) - # Kill the SS plugin process - local pid_file="${TMP_PATH}/test_node_${node_id}_plugin.pid" - [ -s "$pid_file" ] && kill -9 "$(head -n 1 "$pid_file")" >/dev/null 2>&1 - busybox pgrep -af "test_node_${node_id}" | awk '! /socks_auto_switch\.sh/{print $1}' | xargs kill -9 >/dev/null 2>&1 - rm -rf ${TMP_PATH}/test_node_${node_id}*.* - if [ "${_proxy_status}" -eq 200 ]; then - return 0 - fi - } - return 1 + local test_flag="test_node_${id}_${node_id}" + local _type _tmp_port curlx _proxy_status pid_file + ( + exec 9>&- + exec 8>"${LOCK_PATH}/${CONFIG}_socks_auto_switch_test.lock" + flock -x 8 || exit 1 + _type=$(echo $(config_n_get ${node_id} type) | tr 'A-Z' 'a-z') + [ -n "${_type}" ] && { + check_process + _tmp_port=$(get_new_port 48800 tcp,udp) || exit 1 + NO_REC_PROCESS=1 "$APP_FILE" run_socks flag="$test_flag" node="$node_id" bind=127.0.0.1 socks_port="$_tmp_port" config_file="${test_flag}.json" 8>&- 9>&- + sleep 2s 8>&- 9>&- + curlx="socks5h://127.0.0.1:${_tmp_port}" + _proxy_status=$(test_url "${probe_url}" ${retry_num} ${connect_timeout} "-x $curlx" 1) + # Kill the SS plugin process. + pid_file="${TMP_PATH}/${test_flag}_plugin.pid" + [ -s "$pid_file" ] && kill -9 "$(head -n 1 "$pid_file")" >/dev/null 2>&1 + busybox pgrep -af "${TMP_PATH}/${test_flag}[._]" | awk '! /socks_auto_switch\.sh/{print $1}' | xargs -r kill -9 >/dev/null 2>&1 + rm -f "$TMP_PATH/${test_flag}"*.* + if [ "${_proxy_status}" -eq 200 ]; then + exit 0 + fi + } + exit 1 + ) } try_switch_backup() { @@ -122,23 +129,23 @@ try_switch_backup() { if test_node ${new_node}; then check_process log_i18n 0 "Socks switch detection: Port [%s] [%s:[%s]] normal, switch to this node!" "${socks_port}" "${node_type}" "${node_remarks}" - NO_REC_PROCESS=1 $APP_FILE socks_node_switch flag=${id} new_node=${new_node} - [ $? -eq 0 ] && { + if NO_REC_PROCESS=1 "$APP_FILE" socks_node_switch flag="$id" new_node="$new_node" 9>&-; then log_i18n 0 "Socks switch detection: Port [%s] node switch complete!" "${socks_port}" - } - return 0 + return 0 + fi + log_i18n 0 "Socks switch detection: Port [%s] node switch failed, continue trying other nodes!" "${socks_port}" + else + log_i18n 0 "Socks switch detection: Port [%s] [%s:[%s]] abnormal." "${socks_port}" "${node_type}" "${node_remarks}" fi - log_i18n 0 "Socks switch detection: Port [%s] [%s:[%s]] abnormal." "${socks_port}" "${node_type}" "${node_remarks}" now_node="$new_node" tried=$((tried + 1)) done - log_i18n 0 "Socks switch detection: Port [%s] all nodes are unavailable!" "${socks_port}" + log_i18n 0 "Socks switch detection: Port [%s] all nodes are unavailable or switching failed!" "${socks_port}" return 1 } test_auto_switch() { - flag=$((flag + 1)) local b_nodes=$1 local now_node=$2 [ -z "$now_node" ] && { @@ -150,9 +157,7 @@ test_auto_switch() { fi } - [ $flag -le 1 ] && main_node=$now_node - - local status=$(test_proxy) + local status=$(test_proxy 9>&-) if [ "$status" = "2" ]; then log_i18n 0 "Socks switch detection: Port [%s] Unable to connect to the network. Please check if the network is working properly!" "${socks_port}" return 2 @@ -163,13 +168,13 @@ test_auto_switch() { test_node ${main_node} [ $? -eq 0 ] && { check_process - # The main node is working properly; switch to the main node. log_i18n 0 "Socks switch detection: Port [%s] Primary node [%s: [%s]] is normal. Switch to the primary node!" "${socks_port}" "$(config_n_get $main_node type)" "$(config_n_get $main_node remarks)" - NO_REC_PROCESS=1 $APP_FILE socks_node_switch flag=${id} new_node=${main_node} - [ $? -eq 0 ] && { + if NO_REC_PROCESS=1 "$APP_FILE" socks_node_switch flag="$id" new_node="$main_node" 9>&-; then log_i18n 0 "Socks switch detection: Port [%s] node switch complete!" "${socks_port}" - } - return 0 + return 0 + fi + log_i18n 0 "Socks switch detection: Port [%s] failed to restore the primary node!" "${socks_port}" + status=1 } fi @@ -186,6 +191,8 @@ test_auto_switch() { start() { id=$1 LOCK_FILE=${LOCK_PATH}/${CONFIG}_socks_auto_switch_${id}.lock + exec 9>"$LOCK_FILE" + flock -n 9 || return 0 main_node=$(config_n_get $id node) socks_port=$(config_n_get $id port 0) delay=$(config_n_get $id autoswitch_testing_time 30) @@ -201,7 +208,10 @@ start() { [ "$main_node" = "$backup_node" ] && return elif [ "$backup_node_num" -gt 1 ]; then [ "$restore_switch" != "1" ] && { - [ -z "$(echo $backup_node | grep -F "$main_node")" ] && backup_node="${backup_node} ${main_node}" + case " $backup_node " in + *" $main_node "*) ;; + *) backup_node="${backup_node} ${main_node}" ;; + esac } fi else @@ -209,15 +219,9 @@ start() { return fi while [ -n "$backup_node" ]; do - [ -f "$LOCK_FILE" ] && { - sleep 6s - continue - } check_process - touch $LOCK_FILE test_auto_switch "$backup_node" - rm -f $LOCK_FILE - sleep ${delay} + sleep ${delay} 9>&- done } diff --git a/luci-app-ssr-plus/root/etc/init.d/shadowsocksr b/luci-app-ssr-plus/root/etc/init.d/shadowsocksr index 8ee87555..98d34df5 100755 --- a/luci-app-ssr-plus/root/etc/init.d/shadowsocksr +++ b/luci-app-ssr-plus/root/etc/init.d/shadowsocksr @@ -2974,8 +2974,8 @@ start_rules() { esac } - if [ "$(uci_get_by_type global dports)" = "3" ]; then - custom_ports=$(uci_get_by_name "$GLOBAL_SERVER" custom_ports) # custom_ports 存储了用户自定义的端口 + if [ "$(uci_get_by_type global dports 1)" = "3" ]; then + custom_ports=$(uci_get_by_type global custom_ports) # custom_ports 存储了用户自定义的端口 if [ -n "$custom_ports" ]; then proxyport="-m multiport --dports $custom_ports" fi @@ -3017,7 +3017,7 @@ start_rules() { -G "$(uci_get_by_type access_control lan_gm_ips)" \ -m "$(uci_get_by_type access_control Interface)" \ -D "$proxyport" \ - "$(get_arg_out)" "$(gfwmode)" "$ARG_UDP" "$ARG_UDP_RULES" "$ARG_A" + $(get_arg_out) $(gfwmode) $ARG_UDP $ARG_UDP_RULES $ARG_A return $? } diff --git a/luci-app-ssr-plus/root/usr/bin/ssr-monitor b/luci-app-ssr-plus/root/usr/bin/ssr-monitor index 608a4f38..3d22988a 100755 --- a/luci-app-ssr-plus/root/usr/bin/ssr-monitor +++ b/luci-app-ssr-plus/root/usr/bin/ssr-monitor @@ -87,7 +87,7 @@ while [ "1" == "1" ]; do #死循环 #redir tcp if [ "$redir_tcp_process" -gt 0 ]; then icount=$(redir_tcp_running) - local tcp_expected="$redir_tcp_process" + tcp_expected="$redir_tcp_process" if [ "$GLOBAL_TYPE" = "socks5" ]; then tcp_expected="$EXPECTED_THREADS" fi @@ -101,7 +101,7 @@ while [ "1" == "1" ]; do #死循环 #redir udp if [ "$redir_udp_process" -gt 0 ]; then icount=$(redir_udp_running) - local udp_expected="$redir_udp_process" + udp_expected="$redir_udp_process" if [ "$GLOBAL_TYPE" = "socks5" ]; then udp_expected="$EXPECTED_THREADS" fi @@ -172,12 +172,12 @@ while [ "1" == "1" ]; do #死循环 echolog "chinadns-ng $dnsserver tunnel error.restart!" dnsserver=$(uci_get_by_type global chinadns_ng_tunnel_forward 8.8.4.4:53) kill -9 $(ps_list | grep "chinadns-ng -b 127.0.0.1 -l $tmp_dns_port" | grep -v grep | awk '{print $1}') >/dev/null 2>&1 - local chinadns_ng_proto="$(uci_get_by_type global chinadns_ng_proto)" - local chinadns_ng_dns="" + chinadns_ng_proto="$(uci_get_by_type global chinadns_ng_proto)" + chinadns_ng_dns="" IFS=',' for chinadns_ng_server in $dnsserver; do - local chinadns_ng_ip="${chinadns_ng_server%%:*}" - local chinadns_ng_port="${chinadns_ng_server##*:}" + chinadns_ng_ip="${chinadns_ng_server%%:*}" + chinadns_ng_port="${chinadns_ng_server##*:}" [ "$chinadns_ng_ip" = "$chinadns_ng_port" ] && chinadns_ng_port="53" chinadns_ng_tls_port="853" case "$chinadns_ng_proto" in